I fall into this while writing a data generator for sample objects.
Let us assume this:
public class SampleItem
{
public string name { get; set; }
public SampleItem() { }
}
public class SampleClass
{
public List<SampleItem> ObjectList { get; set; }
public SampleClass() { }
}
Using Reflection, the data generator can easily see and assign a string value to SampleItem.Name property (notice: at runtime, our code does not know what SampleItem is)
For my purpose, it was important to insert some sample items into any List<T> property of an object.
In the above sample code that means, for a SampleClass instance, to generate a list of SampleItem to be assigned to the instance's ObjetcList property.
An elegant solution was found here. Its code is so simple:
public static object ConvertList(List<object> value, Type type) { var containedType = type.GenericTypeArguments.First(); return value.Select(item => Convert.ChangeType(item, containedType)); }
Example usage:
var objects = new List<Object> { 1, 2, 3, 4 }; ConvertList(objects, typeof(List<int>)).Dump();
|
That didn't work for my case. I could not assign the ObjectList property (I got an exception) because the resulting value generated by the code above was in fact a Lis<object>. It only converted the items contained into the list into SampleItem, the list itself was not a List<SampleItem> it was still a List<object>
The solution (less elegant, but still efficientJ):
static object ConvertList(IEnumerable<object> value, Type listType)
{
var containedType = listType.GenericTypeArguments.First();
var tmpList = value.Select(item => Convert.ChangeType(item, containedType)).ToList();
var newList = Activator.CreateInstance(listType);
MethodInfo addMethod = listType.GetMethod("Add");
foreach(var item in tmpList)
addMethod.Invoke(newList, new object[] { item });
return newList;
}
That converts a List<object> and returns an object of the type expected by the property (a List<T>)