4

我动态创建了一个类(在这里找到),但我不明白为什么我不能用它来创建一个列表?

var myType = CompileResultType();
var myObject = Activator.CreateInstance(myType);
var myList = new List<myObject>();

// Error: The type or namespace name 'myObject' 
// could not be found (are you missing a using directive 
// or an assembly reference?)

我该怎么做?

4

5 回答 5

8

它们被称为泛型类型参数,因为它们需要类型,而不是实例。因此,您需要知道实际类型或使用反射创建列表对象。

Type listType = typeof(List<>);
Type dynamicClassType = listType.MakeGenericType(myObject.GetType());
object myList = Activator.CreateInstance(dynamicClassType);

但是,您无法以任何有意义的方式使用该实例,因为它是一个对象。

  • 您可以按照Avner Shahar-Kashtan 的回答IList中的建议将其转换为a并使用非泛型方法。

    IList myList = (IList)Activator.CreateInstance(dynamicClassType);
    
  • 您也可以通过反射调用列表实例的方法。

    // roughly
    MethodInfo addMethod = myList.GetType().GetMethod("Add");
    addMethod.Invoke(myList, objectToAdd);
    
  • 或者按照Cuong Le 的回答中的建议进行操作并dynamic用作列表实例的类型。

    dynamic myList = Activator.CreateInstance(dynamicClassType);
    
于 2013-07-23T06:13:59.783 回答
6

为了动态构造泛型类型,您必须使用反射,特别是MakeGenericType方法。像这样的东西:

Type baseListType = typeof(List<>); // get the generic List<>
Type myType = CompileResultType; // same as in yours.
Type myListType = baseListType.MakeGenericType(myType); // Get the List<MyType>
IList myList = (IList)Activator.CreateInstance(myListType); // Instantiate.

请注意,我定义myListIList,因为我们没有它的编译时类型。幸运的是,我们有方便的基类和接口,例如IListIEnumerable以及其他几个List<T>我们可以使用的实现。

于 2013-07-23T06:14:29.247 回答
2

泛型类型需要类的类型,而不是实例,也许你需要:

var myType = CompileResultType();
var listType = typeof (List<>).MakeGenericType(myType);
var myList = Activator.CreateInstance(listType);

但是myList在这里object,如果您想在列表中添加或删除项目,您应该利用dynamic

dynamic myList = Activator.CreateInstance(listType);

所以你可以打电话:

myList.Add(...);
于 2013-07-23T06:14:09.620 回答
1

这将创建列表类型List<WhatEverIsInMyType>

var listType = typeof(List<>).MakeGenericType(myType);

现在您需要创建一个实例,但您已经介绍过:

var list = Activator.CreateInstance(listType);

不幸的是,我们正在使用反射,因此在编译时不知道确切的类型,但并非所有类型都丢失了,您可以使用非泛型类型:

    var list = (IList)Activator.CreateInstance(listType);

现在您可以使用诸如Add Remove使用列表之类的方法,但要小心,因为如果类型不数学,您将获得运行时异常。

于 2013-07-23T06:15:38.013 回答
0

您使用的是类型,而不是实例。假设CompileResultType()回报MyType

MyType myType = CompileResultType();
List<MyType> list = new List<MyType>();

我不确定您为什么要使用Activator.CreateInstance()...

于 2013-07-23T06:14:17.690 回答