Create a generic list using reflection
I have a function that uses reflection to set properties of object A from object B. At one point, I need to instantiate a generic collection. However, I am unable to get it working. Here is what I have now:
IList list = destProperty.PropertyType.GetGenericTypeDefinition()
.MakeGenericType(destProperty.PropertyType.GetGenericArguments())
.GetConstructor(Type.EmptyTypes)
.Invoke(null) as IList;
I am trying to set the value of the destProperty. It has to be a List At runtime, the开发者_如何学编程 destProperty is of type ICollection<>. I think what's happening is that since ICollection is an interface, it has no constructor. What is the proper way to instantiate it then?
Thanks!
I've re-written your code, into the form of an example (hopefully that matches what you're trying to do! =), to try and make it clearer what the problem is:
public class Program
{
public struct MyType
{
public ICollection<string> MyProperty { get; set; }
}
static void Main(string[] args)
{
var type = typeof(MyType);
var properties = type.GetProperties();
var destProperty = properties[0];
var genericTypeDefinition = destProperty.PropertyType.GetGenericTypeDefinition();
var madeGenericType = genericTypeDefinition.MakeGenericType(destProperty.PropertyType.GetGenericArguments());
var ctor = madeGenericType.GetConstructor(Type.EmptyTypes);
}
}
If you put a breakpoint on the penultimate brace you'll see that ctor
comes back as null
, which is because, as you correctly surmised, ICollection<T>
doesn't have any constructors due to it being an interface.
Because of this, there's no "super-generic" way of doing this because there's no inherent way to say "what's the best implementation of ICollection<T>
to use in this situation". You'll need to make that decision and new
one, based on the information you get back from reflection.
You can't instantiate an interface. What you can do is instantiate a generic type that implements that interface. In your case, you'll want to get the Type representing the generic List<>, then call MakeGenericType on it.
That assumes that you know List will always work. If not, I suppose you could search for types that implement the interface, but how you'd pick one and be sure it has a parameterless constructor seems complicated to me. Seems like it would be easier to get the actual type of the object rather than the interface in that case.
One technique is to declare a static method taking the same generic arguments as the list you want to create. Then you can pull the arguments from the property to invoke the method.
Type interfaceType = destProperty.PropertyType;
return typeof(MyClass)
.GetMethod("CreateList", BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(interfaceType.GetGenericArguments())
.Invoke(null, new object[] { });
private static IList CreateList<T>()
{
return new List<T>();
}
精彩评论