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 work
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>();
}
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.
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.