sorry I don't speak VB, so here's the C# code I am trying to render with the CodeDom
(this all works peachy rendering to C# just not VB)
var value = new System.Collections.Generic.KeyValuePair<string, int>[0];
var expression = CodeDomUtility.Serialize(value);
(thanks to Richard Demming in the comments for helping me get a proper repro)
Can someone show me a codeDom tree for this that will produce VB code which doesn't syntax error when generated?
when i use the class on some arrays i've generated i get stuff like this in the VB
.. New System.Collections.Generic.KeyValuePair(-1Of String, Integer)() {}
but only for the empty ones. The arrays with items in them work fine.
I've even tried special casing for empty arrays and declaring them without initializers in the codedom
What I have tried:
The big work is commented - the special case for KeyValuePair but it's all interrelated
static partial class CodeDomUtility
{
static CodeExpression _SerializeArray(Array arr)
{
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
{
if (val.GetType().FullName.StartsWith("System.Collections.Generic.KeyValuePair`2"))
{
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));
}
}