使用反射创建通用列表

时间:2010-09-03 13:53:15

标签: .net generics reflection

我有一个使用反射来设置对象A的属性的函数。 有一次,我需要实例化一个通用集合。但是,我无法让它工作。这就是我现在所拥有的:

IList list = destProperty.PropertyType.GetGenericTypeDefinition()
                .MakeGenericType(destProperty.PropertyType.GetGenericArguments())
                .GetConstructor(Type.EmptyTypes)
                .Invoke(null) as IList;

我正在尝试设置destProperty的值。它必须是一个列表 在运行时,destProperty的类型为ICollection<&gt ;.我认为发生的事情是因为ICollection是一个接口,它没有构造函数。那么实例化它的正确方法是什么?

谢谢!

3 个答案:

答案 0 :(得分:2)

我已经将你的代码重新编写成一个例子的形式(希望这与你想要做的事情相符!=),试着让它更清楚地解决问题所在:

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);
    }
}

如果你在倒数第二个支撑上放置一个断点,你会看到ctornull的形式返回,这是因为正如你所推测的那样,ICollection<T>没有构造函数,因为它是一个接口。

正因为如此,没有“超级通用”方式这样做,因为没有固有的方式来说明“在这种情况下使用ICollection<T>的最佳实现”。根据您从反思中获得的信息,您需要做出决定并new

答案 1 :(得分:0)

您无法实例化界面。您可以做的是实例化实现该接口的泛型类型。在您的情况下,您将需要获取表示通用List&lt;&gt;的Type,然后在其上调用MakeGenericType。

假设您知道List将始终有效。如果没有,我想你可以搜索实现接口的类型,但是你如何选择一个并确保它有一个无参数构造函数对我来说似乎很复杂。在这种情况下,似乎更容易获得对象的实际类型而不是接口。

答案 2 :(得分:0)

一种技术是声明一个静态方法,它采用与您要创建的列表相同的通用参数。然后,您可以从属性中提取参数以调用方法。

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