C# 如何使用反射创建的列表作为正常创建列表

C# 如何使用反射创建的列表作为正常创建列表,c#,list,generics,reflection,C#,List,Generics,Reflection,我使用本文中的方法创建了一个列表 Assembly=Assembly.Load(“控制台应用程序4”); 类型mytype=assembly.GetType(“ConsoleApplication4.TestClass”); Type genericList=typeof(List)。MakeGenericType(mytype); var mylist=Activator.CreateInstance(genericList); 我的问题是,创建列表后,如何在如下函数中使用列表: publ

我使用本文中的方法创建了一个列表

Assembly=Assembly.Load(“控制台应用程序4”);
类型mytype=assembly.GetType(“ConsoleApplication4.TestClass”);
Type genericList=typeof(List)。MakeGenericType(mytype);
var mylist=Activator.CreateInstance(genericList);
我的问题是,创建列表后,如何在如下函数中使用列表:

public void TestFunction<T>(List<T> mylist)
{
//do something here
}
public void TestFunction(列表mylist)
{
//在这里做点什么
}

您不能以您想要的方式使用mylist实例,因为编译器无法推断列表的关闭类型。您只能使用进一步的反射方法或使用打开的泛型类型检查它。

您将丢失静态类型分析和编译时检查(然后,假设您正在使用已经发生的反射),因此您可以重新编写
TestFunction

public void TestFunction(dynamic myList)
{
  // do something here
}

您可以简单地更改实例化列表的最后一行

dynamic mylist = Activator.CreateInstance(genericList);
这样,编译器就不会试图推断myList的(运行时)类型,而是将此任务推迟到DLR,在您的情况下,DLR会很高兴地告诉您它是某种
列表

如果您知道mylist的具体类型,当然也可以使用简单的cast

TestFunction((List<knownType>)mylist);
TestFunction((列表)mylist);
选择哪一个主要取决于品味,两者之间可能存在性能差异,但与基于反射的实例化相比,这种差异可能不会成为瓶颈,但如果主要关注性能,请使用探查器


我建议在实例化站点而不是在方法签名中使用dynamic的原因是使大多数代码静态类型化,以便编译器可以检查大多数代码。通过在方法签名中使用dynamic,您将使该方法的所有调用成为动态调用,而如果您将mylist动态类型化,则只会使使用mylist的语句成为动态调用。

获取对该方法的引用(例如通过
myType.GetMethod(“TestFunction”)
)然后利用该方法将其转换为正确的泛型调用:
myMethodInfo.MakeGenericMethod(mytype)
。然后您可以利用它上的方法并传入您的
myList
对象。@ChrisSinclair:我可能错了,但我认为问题是您不能将其作为
List
的对象传递,因为您不能强强制转换它。@AndrewCoonce:不,您不能将其转换为编译时引用(除非您硬编码了它,这就引出了一个问题,为什么您首先要使用反射)。这就是为什么我在那里调用了
MakeGenericMethod
。它将创建一个版本的
TestFunction
(其中
mytype
是底层的
ConsoleApplication4.TestClass
)。然后,您可以简单地对生成的方法信息使用
Invoke
方法,您将在示例代码tcao中已创建的
列表mylist
中传递该方法。总体而言,很难说什么是最佳的操作过程(反射、动态或重构)因为tcao并没有为我们提供太多关于他/她为什么或如何做他们正在做的事情的背景。@chrisnclair:我明白了,这是一种非常酷的技术。
TestFunction((List<knownType>)mylist);