Taoffi's blog

prisonniers du temps

Convert a List<T> to List<something known only at runtime>

I fall into this while writing a data generator for sample objects.

Let us assume this:

 

public class SampleItem
{
public string name { getset; }
public SampleItem() { }
}

 

public class SampleClass
{
public List<SampleItem> ObjectList {  getset; }
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>)