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

标签 c# linq generics reflection

<分区>

编辑:

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

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

所以,我真正想做的是:

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




原帖:

嗨!

我正在尝试遍历命名空间中的所有接口(interface),并将它们作为参数发送给这样的通用方法:

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

我收到“无法将运算符‘<’应用于‘方法组’和‘System.Type’类型的操作数” 关于如何解决这个问题的任何想法?

最佳答案

编辑:好的,是时候进行一个简短但完整的程序了。基本答案和以前一样:

  • 使用 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
        }
    }
}

原始答案

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

你必须通过反射来调用它。泛型的要点是在编译 时进行更多类型检查。您不知道编译时的类型是什么 - 因此您必须使用泛型。

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

你的接口(interface)类型本身真的是通用的吗?我问是因为你在上面调用 MakeGenericType,但没有传入任何类型参数......你是想调用

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

Method<MyNamespace.Interface>();

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

关于c# - 使用仅在执行时已知的类型参数调用泛型方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/325156/

相关文章:

c# - 使用 LINQ,如何从列表中查找具有给定属性值的对象?

spring-mvc - 如何将通用集合类对象作为参数传递

java - 通用多维数组转换函数

Linq 独特的值(value)观

c# - 使用枚举上的 XOR 运算符重载 GetHashCode 和相等运算符

c# - 我应该以编程方式内联所有 CSS 文件以优化页面加载速度吗?

c# - 由于 XmlSerialization (sgen.exe) 无法在 Visual Studio 2022 中构建项目并且无法禁用

c# - 如何从(我认为)没有标准格式的 XML 中检索值?

swift - 在泛型类中传递泛型参数

c# - 使用 shellExecute 运行 c# 控制台应用程序