The Problem:
Hey folks, I am having a strange issue that is starting to really frustrate me. I have searched high and low for the answer, and tried many different things, but for some reason I cannot get this code working.
I am using reflection to to convert an array of anonymous objects to specific types, based on the type of T. Now before it is mentioned, yes reflection is the only way to do what I am doing (converting a script language to Type Strong C# objects).
My issue is on lines 35 - 43. If the value type is that of a List{T}, then I first check if it is null... If so, I create a new list using Activator.CreateInstance() (line 58), otherwise use the existing list. The issue I am facing here is that the Value is ALWAYS NULL when this method is called, even though I am setting the Value on line 43. That means the list will never have more than 1 item in it, even if I am adding more than 1 item...
On lines 23 and 51, you can see that I set the Value for other types, and it works perfectly, so what am I doing wrong on lines 34-43 that are preventing this code from working correctly?
The Code:
You can view this code with line numbers on pastebin or below:
public class ObjectProperty<T> : ObjectPropertyBase
{
/// <summary>
/// Gets or Sets the value for this property
/// </summary>
public T Value;
/// <summary>
/// Takes an array of string values, and converts it to the proper value type for
/// this instance's Generic Type
/// </summary>
/// <param name="ValueParams">The string value's to convert, and set the
/// Value of this instance to.
/// </param>
public override void SetValueFromParams(String[] ValueParams)
{
Type PropertyType = typeof(T);
// Check for array's, as they are handled differently
if (PropertyType.IsArray)
{
// Set the value to the instanced object
Value = (T)ConvertArray(ValueParams, PropertyType);
}
else if (PropertyType.IsGenericType)
{
// Grab our types interfaces and generic types
Type[] interfaces = PropertyType.GetInterfaces();
Type[] types = PropertyType.GetGenericArguments();
// Check for List<T>
if (interfaces.Any(i => i == typeof(IList)))
{
// Grab our current list... if the Value isnt created yet, make it
dynamic obj = (dynamic)Value ?? CreateList(types);
// Add our value to the list
if (types[0].IsArray)
obj.Add(ConvertArray(ValueParams, types[0]));
else
obj.Add(ConvertValue<dynamic>(ValueParams[0], types[0]));
Value = (T)obj;
}
else
throw new Exception($"Invalid Generic Type found \"{PropertyType}\"");
}
else
{
// Since we are not an array, extract our only value
Value = ConvertValue<T>(ValueParams[0], PropertyType);
}
}
protected static IList CreateList(Type[] genericTypes)
{
Type obj = typeof(List<>).MakeGenericType(genericTypes);
return (IList)Activator.CreateInstance(obj);
}
/// <summary>
/// Converts the object value into the Typed variant of this <see cref="Value"/>
/// </summary>
protected K ConvertValue<K>(object Value, Type PropertyType)
{
// No need to change type if types match
if (Value.GetType() == PropertyType)
return (K)Value;
// Enums need special care
if (PropertyType.IsEnum)
return (K)Enum.Parse(PropertyType, Value.ToString(), true);
return (K)Convert.ChangeType(Value, PropertyType);
}
/// <summary>
/// Converts the object array values into the Typed variant of this <see cref="Value"/>
/// </summary>
protected object ConvertArray(Object[] values, Type propertyType)
{
// Set the value to the instanced object
switch (propertyType.Name.ToLowerInvariant())
{
case "int[]":
case "int32[]":
return Array.ConvertAll(values, Convert.ToInt32);
case "string[]":
return Array.ConvertAll(values, Convert.ToString);
case "double[]":
return Array.ConvertAll(values, Convert.ToDouble);
default:
throw new Exception("Invalid property type: " + propertyType.Name);
}
}
}
Thank you for having a look at my problem, hopefully someone can help me get this figured out.
Aucun commentaire:
Enregistrer un commentaire