I overheard an interesting question today: how to create a generic list instance when we don’t know the type at compile time? I’m sure there are lots of great answers to this out there on the intrawebs (this won’t be one of them), but I thought I’d give it a quick go myself as it doesn’t sound too tricky to get working for the most basic of cases, and it would also help my reflecton-fu which is fairly lacking.
Here is the test I would like to pass:
[Test] public void CreateAGenericListFromAType() { var list = (IList<int>) CreateList(typeof (int), new object[] {1, 2, 3}); Assert.That(list, Is.EquivalentTo(new[] {1,2,3})); }
So given a Type
(in this case an int
), we want CreateList(...)
to return the equivalent of an IList<Type>
. Of course the compiler won’t have a reference to the exact type when compiling CreateList(...)
, and generic types have to be closed at compile time for us to work with them normally. This means we will have to resort to reflection. Here’s one way of passing the test:
IList CreateList(Type type, object[] objects) { var genericListType = typeof (List<>); var specificListType = genericListType.MakeGenericType(type); var list = (IList) Activator.CreateInstance(specificListType); foreach (var o in objects) { list.Add(Convert.ChangeType(o, type)); } return list; }
Here we close the list type down using MakeGenericType()
, then use Activator.CreateInstance()
(yuk) to instantiate our dynamically, generically-typed list. I’m also choosing to work with the non-generic IList
interface, as this means I don’t need to resort to reflection to call the Add(T)
method.
I’m probably overlooking lots of details, but at least this basic approach passed the test.
Update: As expected, a StackOverflow answer has a neater way that avoids using Activator
.