仅在执行时调用types参数的generics方法

编辑:

当然,我真正的代码看起来不像这样。 我试图编写半伪代码,使其更清楚我想做的事情。

看起来只是把事情搞砸了。

所以,我真正想要做的是这样的:

Method<Interface1>(); Method<Interface2>(); Method<Interface3>(); ... 

那么…我想也许我可以把它变成一个循环使用reflection。 所以问题是:我该怎么做。 我对反思的知识浅。 所以代码示例会很好。

该scheme如下所示:

 public void Method<T>() where T : class {} public void AnotherMethod() { Assembly assembly = Assembly.GetExecutingAssembly(); var interfaces = from i in assembly.GetTypes() where i.Namespace == "MyNamespace.Interface" // only interfaces stored here select i; foreach(var i in interfaces) { Method<i>(); // Get compile error here! } 

原文:

嗨!

我试图循环通过命名空间中的所有接口,并将它们作为参数发送到像这样的通用方法:

 public void Method<T>() where T : class {} public void AnotherMethod() { Assembly assembly = Assembly.GetExecutingAssembly(); var interfaces = from i in assembly.GetTypes() where i.Namespace == "MyNamespace.Interface" // only interfaces stored here select i; foreach(var interface in interfaces) { Method<interface>(); // Get compile error here! } } 

我得到的错误是“types名称预期,但本地variables名称find”。 如果我尝试

 ... foreach(var interface in interfaces) { Method<interface.MakeGenericType()>(); // Still get compile error here! } } 

我得到“不能应用运算符'<'types'方法组'和'System.Type'types的操作数”任何想法如何解决这个问题?

编辑:好的,时间短但完整的程序。 基本的答案和以前一样:

  • 用Type.GetMethodfind“打开”的generics方法
  • 使用MakeGenericMethod进行通用化
  • 用Invoke调用它

这是一些示例代码。 请注意,我将查询expression式更改为点符号 – 当您基本上只有一个where子句时,使用查询expression式没有意义。

 using System; using System.Linq; using System.Reflection; namespace Interfaces { interface IFoo {} interface IBar {} interface IBaz {} } public class Test { public static void CallMe<T>() { Console.WriteLine("typeof(T): {0}", typeof(T)); } static void Main() { MethodInfo method = typeof(Test).GetMethod("CallMe"); var types = typeof(Test).Assembly.GetTypes() .Where(t => t.Namespace == "Interfaces"); foreach (Type type in types) { MethodInfo genericMethod = method.MakeGenericMethod(type); genericMethod.Invoke(null, null); // No target, no arguments } } } 

原始答案

让我们抛开调用variables“接口”开始的显而易见的问题。

你必须通过反思来调用它。 generics的要点是在编译时进行更多的types检查。 编译时你不知道types是什么 – 因此你必须使用generics。

获取generics方法,并调用MakeGenericMethod,然后调用它。

你的接口types本身实际上是通用的? 我问,因为你打电话给MakeGenericType,但没有传入任何types的参数…你想打电话

 Method<MyNamespace.Interface<string>>(); // (Or whatever instead of string) 

要么

 Method<MyNamespace.Interface>(); 

如果是后者,则只需调用MakeGenericMethod – 而不是MakeGenericType。