Как сделать массаж codedom для генерации этого кода в правильном ВБ?
извините, что я не говорю на VB, так что вот код C#, который я пытаюсь визуализировать с помощью CodeDom
(все это работает персиковый рендеринг на C# только не VB)
var value = new System.Collections.Generic.KeyValuePair<string, int>[0]; var expression = CodeDomUtility.Serialize(value);
(спасибо Ричарду Деммингу в комментариях за то, что он помог мне получить правильный упрек)
Может ли кто-нибудь показать мне дерево codeDom для этого, которое будет производить VB-код, который не содержит синтаксической ошибки при создании?
когда я использую класс на некоторых массивах, которые я сгенерировал, я получаю такие вещи в VB
.. New System.Collections.Generic.KeyValuePair(-1Of String, Integer)() {}
но только для пустых. Массивы с элементами в них работают нормально.
Я даже пробовал специальную оболочку для пустых массивов и объявлял их без инициализаторов в codedom
Что я уже пробовал:
Большая работа комментируется - особый случай для KeyValuePair, но все это взаимосвязано
static partial class CodeDomUtility { static CodeExpression _SerializeArray(Array arr) { // TODO: Spitting out garbage on empty SZ arrays in VB, with spurious -1's in the code // of the array declaration and i have no idea why. if (1 == arr.Rank && 0 == arr.GetLowerBound(0)) { var result = new CodeArrayCreateExpression( arr.GetType()); foreach (var elem in arr) result.Initializers.Add(Serialize(elem)); return result; } throw new NotSupportedException("Only SZArrays can be serialized to code."); } public static CodeExpression Serialize(object val) { if (null == val) return new CodePrimitiveExpression(null); if (val is bool || val is string || val is short || val is ushort || val is int || val is uint || val is ulong || val is long || val is byte || val is sbyte || val is float || val is double || val is decimal || val is char) { return new CodePrimitiveExpression(val); } if (val is Array && 1 == ((Array)val).Rank && 0 == ((Array)val).GetLowerBound(0)) { return _SerializeArray((Array)val); } var conv = TypeDescriptor.GetConverter(val); if (null != conv) { if (conv.CanConvertTo(typeof(InstanceDescriptor))) { var desc = conv.ConvertTo(val, typeof(InstanceDescriptor)) as InstanceDescriptor; if (!desc.IsComplete) throw new NotSupportedException(string.Format("The type \"{0}\" could not be serialized.", val.GetType().FullName)); var ctor = desc.MemberInfo as ConstructorInfo; if (null != ctor) { var result = new CodeObjectCreateExpression(ctor.DeclaringType); foreach (var arg in desc.Arguments) result.Parameters.Add(Serialize(arg)); return result; } throw new NotSupportedException(string.Format("The instance descriptor for type \"{0}\" is not supported.", val.GetType().FullName)); } else { // we special case for KeyValuePair types. // TODO: research a better way to do this if (val.GetType().FullName.StartsWith("System.Collections.Generic.KeyValuePair`2")) { // TODO: Find out what needs to happen to make it work with VB var kvpType = new CodeTypeReference(typeof(KeyValuePair<,>)); foreach (var arg in val.GetType().GetGenericArguments()) kvpType.TypeArguments.Add(arg); var result = new CodeObjectCreateExpression(kvpType); for(int ic= kvpType.TypeArguments.Count,i = 0;i<ic;++i) { var prop = val.GetType().GetProperty(0==i?"Key":"Value"); result.Parameters.Add(Serialize(prop.GetValue(val))); } return result; } throw new NotSupportedException(string.Format("The type \"{0}\" could not be serialized.", val.GetType().FullName)); } } else throw new NotSupportedException(string.Format("The type \"{0}\" could not be serialized.", val.GetType().FullName)); } }
Richard Deeming
Ваш код, кажется, работает для меня:
Демонстрация[^]
Тот самый VB.NET выход есть:
New System.Collections.Generic.KeyValuePair(Of Integer, String)() {New System.Collections.Generic.KeyValuePair(Of Integer, String)(-21, "ab")}
NB: То "исследуйте лучший способ сделать это" это похоже на ваш вопрос на днях:
Type valType = val.GetType(); if (valType.IsGenericType && valType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
honey the codewitch
- Упрекнул я Ричарда. Проверьте свою демо - ссылку
Richard Deeming
Моя демонстрационная ссылка все еще показывает тот же код и результаты. Вы нажали кнопку "Сохранить" и получили новую ссылку?
honey the codewitch
возгласы. извините, никогда раньше не пользовался этим сайтом. я думал, что он просто отредактирован на месте.
вот ты где: Демонстрация
Richard Deeming
Ладно, похоже, это как-то связано с пустым массивом. Изменение значения на:
var value = new System.Collections.Generic.KeyValuePair<string, int>[0];
производит проблематичное VB.NET код:
New System.Collections.Generic.KeyValuePair(-1Of String, Integer)() {}
Обновленная демо-версия[^]
honey the codewitch
я уточню свой вопрос. Спасибо. Я попытался не использовать инициализаторы, а просто установить его в [0] в CodeDom, но это ничего не изменило. Возможно, мне придется использовать специальный случай для VB и вставить объект CodeSnippet, чтобы сделать это =(
спасибо за вашу помощь. Я только что выпил кофе и сегодня утром был медлителен.
Richard Deeming
Определенно выглядит как жучок в VBCodeProvider
. Он не может справиться с массивами любого универсального типа.
Опорный источник[^]
honey the codewitch
у вас есть какой-то серьезный google fu. Наверное, я заржавел. Честно говоря, я хотел объявить эту таблицу DFA простым вложенным массивом int, как мои таблицы синтаксического анализа, но, несмотря на то, что DFA (структура, которую я сериализую выше) концептуально проще, чем PDA (ints, которые я сериализую) математически, структуры данных для них более сложны, чем позволяет такое решение вложенного массива.
Я подумываю о том, чтобы объявить DfaEntry структура и покончим с этим.
Честно говоря я даже не знаю правильного синтаксиса для этого в VB так что я не могу действительно винить VBCodeProvider LOL
honey the codewitch
Спасибо, Ричард. Я думаю, что не сделал РЕПО правильно, потому что тот же код ломается на моей машине.
Я бы дал вам фактические данные, которые я сериализую в codedom, но это страницы длиной.