小编典典

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

c#

编辑:

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

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

所以,我实际上想做的是:

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’的操作数”关于如何解决此问题的任何想法吗?


阅读 275

收藏
2020-05-19

共1个答案

小编典典

编辑:好的,时间短但完整的程序。基本答案与以前相同:

  • 使用Type.GetMethod查找“开放”通用方法
  • 使用MakeGenericMethod使其通用
  • 用调用来调用

这是一些示例代码。请注意,我已将查询表达式更改为点表示法-当您基本上只有一个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。

2020-05-19