我动态创建了一个类(找到它here),但我不明白为什么我不能用它来创建列表?
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?)
我该怎么做?
答案 0 :(得分:8)
它们被称为泛型类型参数,因为它们需要类型,而不是实例。因此,您需要知道实际类型或使用反射创建列表对象。
Type listType = typeof(List<>);
Type dynamicClassType = listType.MakeGenericType(myObject.GetType());
object myList = Activator.CreateInstance(dynamicClassType);
但是,您无法以任何有意义的方式使用实例,因为它是一个对象。
您可以按照Avner Shahar-Kashtan's answer中的建议将其转换为IList
并使用非通用方法。
IList myList = (IList)Activator.CreateInstance(dynamicClassType);
您也可以通过反射调用list-instance的方法。
// roughly
MethodInfo addMethod = myList.GetType().GetMethod("Add");
addMethod.Invoke(myList, objectToAdd);
或按Cuong Le's answer中的建议操作,并使用dynamic
作为列表实例的类型。
dynamic myList = Activator.CreateInstance(dynamicClassType);
答案 1 :(得分:6)
为了动态构造泛型类型,您必须使用Reflection,特别是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.
请注意,我将myList
定义为IList
,因为我们没有编译时类型。幸运的是,我们有方便的基类和接口,如IList
,IEnumerable
和其他几个List<T>
实现的接口,我们可以使用它们。
答案 2 :(得分: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(...);
答案 3 :(得分:1)
这将创建列表List<WhatEverIsInMyType>
的类型:
var listType = typeof(List<>).MakeGenericType(myType);
现在您需要创建一个实例,但您已经涵盖了:
var list = Activator.CreateInstance(listType);
不幸的是我们正在使用反射,因此在编译时不知道确切的类型,但是并非所有类型都丢失,您可以使用非泛型类型:
var list = (IList)Activator.CreateInstance(listType);
现在您可以使用Add
Remove
之类的方法来使用您的列表但要小心,因为如果类型不是数学,您将获得运行时异常。
答案 4 :(得分:0)
<强>分析:强>
这里的问题是你动态地创建一个类型,并且你没有编译时类型名称来引用它。但是,泛型需要使用类型名称。
假设您想要List<string>
。 string
是静态确定的类型名称;你不会先声明一个变量,比如string foo;
,然后将你的列表声明为List<foo>
......你会吗?
就像foo
一样,myObject
不是类型名称 - 它是引用动态类型对象的变量的名称 - 因此您不能将其用作泛型类型参数。同样,List<myType>
也不起作用,因为myType
也不是类型名称;它只是一个引用Type
对象的变量。
<强>建议:强>
如果你仔细想想,在这里使用泛型只是没有用,因为泛型的使用不会增加静态类型的安全性。只需使用ArrayList
代替。
答案 5 :(得分:0)
您使用类型,而非实例。假设CompileResultType()
返回MyType
:
MyType myType = CompileResultType();
List<MyType> list = new List<MyType>();
我不确定你为什么使用Activator.CreateInstance()
但是......