Create a generic list using reflection

前端 未结 3 1396
走了就别回头了
走了就别回头了 2021-01-23 01:42

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

相关标签:
3条回答
  • 2021-01-23 01:51

    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>();
    }
    
    0 讨论(0)
  • 2021-01-23 02:00

    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.

    0 讨论(0)
  • 2021-01-23 02:03

    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.

    0 讨论(0)
提交回复
热议问题