使用仅在执行时已知的类型参数调用泛型方法

编辑:

当然我真正的代码不是这样的。我尝试编写半伪代码,使它更清楚我想做什么。

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

所以,我真正想做的是:

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

我想也许我可以用反射把它变成一个循环。所以问题是: 我该怎么做。我有 非常浅显的反思知识。因此,代码示例将是伟大的。

情况是这样的:

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!
}
}

我得到的错误是“类型名称预期,但局部变量名称发现”。 如果我尝试

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

我得到“不能对类型为‘ method group’和‘ System.Type’的操作数应用运算符‘ <’” 有办法解决这个问题吗?

103556 次浏览

编辑: 好了,现在是一个简短而完整的节目时间。基本的答案和之前一样:

  • 使用 Type.GetMethod 查找“ open”泛型方法
  • 使用 MakeGenericMethod 使其具有通用性
  • 使用 Invoke 调用它

下面是一些示例代码。注意,我将查询表达式更改为点符号-如果只有一个 where 子句,那么使用查询表达式就没有意义了。

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

原始答案

让我们先把调用变量“接口”这个明显的问题放在一边。

你必须用反思来称呼它。泛型的要点是在 编译时放置更多的类型检查。您不知道编译时的类型是什么,因此必须使用泛型。

获取泛型方法,并对其调用 MakeGenericMethod,然后调用它。

您的接口类型本身实际上是通用的吗?我这样问是因为您正在调用它的 MakeGenericType,但是没有传递任何类型参数..

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

或者

Method<MyNamespace.Interface>();

如果是后者,您只需要调用 MakeGenericMethod-而不是 MakeGenericType。