neggenbe
neggenbe

Reputation: 1885

c# Create generic list dynamically at runtime

Following the example on this post, I found out how to create a list of generic types dynamically. Now, my issue is that I want to ADD items to the created list from an unknown source list - is there some way to achieve this?

EDIT I start with a source list containing business objects, but I absolutely need the right type of my output list, because of downstream bindings that require it.

My non-compiling code is as follows:

IList<object> sourceList; // some list containing custom objects
Type t = typeof(IList).MakeGenericType(sourceList[0].GetType());
IList res = (IList)Activator.CreateInstance(t);
foreach (var item in sourceList) {
    reportDS.Add(item); // obviously does not compile
}

Upvotes: 4

Views: 15858

Answers (2)

Dark Falcon
Dark Falcon

Reputation: 44181

I would recommend moving your code into a generic class or function, moving the reflection to a higher level:

private static List<T> CloneListAs<T>(IList<object> source)
{
    // Here we can do anything we want with T
    // T == source[0].GetType()
    return source.Cast<T>().ToList();
}

To call it:

IList<object> sourceList; // some list containing custom objects
// sourceList = ...

MethodInfo method = typeof(this).GetMethod("CloneListAs");
MethodInfo genericMethod = method.MakeGenericMethod(sourceList[0].GetType());

var reportDS = genericMethod.Invoke(null, new[] {sourceList});

Upvotes: 4

Sean
Sean

Reputation: 62472

There's a few reasons this code doesn't work.

Firstly, you need to create an instance of a concrete type. You're taking a non-generic interface (IList) and trying to create a generic type from it. You need typeof(List<>).

Secondly, you're calling AddItem which isn't a method on IList. You need to call Add, which is why the code doesn't compile.

This code will do what you want:

IList<object> sourceList; // some list containing custom objects
Type t = typeof(List<>).MakeGenericType(sourceList[0].GetType());
IList res = (IList)Activator.CreateInstance(t);

foreach(var item in sourceList)
{
    res.Add(item);
}

However, the assumption that sourceList[0] holds the correct type may come to bite you. If that list contains a sequence of objects that are not type compatible with the first item in the list then any attempt to add to res will fail. As was mentioned in the comment, you'd be better off creating a List<object> to hold the items.

Upvotes: 14

Related Questions