C# 如何使用给定的 Type 对象调用泛型方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1408120/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 16:13:06  来源:igfitidea点击:

How to call generic method with a given Type object?

c#.netgenericsreflectiontypes

提问by codymanix

I want to call my generic method with a given type object.

我想用给定的类型对象调用我的泛型方法。

void Foo(Type t)
{
     MyGenericMethod<t>();
}

obviously doesn't work.

显然不起作用。

How can I make it work?

我怎样才能让它工作?

采纳答案by Erik van Brakel

Your code sample won't work, because the generic method expects a type identifier, not a an instance of the Type class. You'll have to use reflection to do it:

您的代码示例将不起作用,因为泛型方法需要类型标识符,而不是 Type 类的实例。你必须使用反射来做到这一点:

public class Example {

    public void CallingTest()
    {
        MethodInfo method = typeof (Example).GetMethod("Test");
        MethodInfo genericMethod = method.MakeGenericMethod(typeof (string));
        genericMethod.Invoke(this, null);

    }

    public void Test<T>()
    {
        Console.WriteLine(typeof (T).Name);
    }
}

Do keep in mind that this is very brittle, I'd rather suggest finding another pattern to call your method.

请记住,这非常脆弱,我宁愿建议寻找另一种模式来调用您的方法。

Another hacky solution (maybe someone can make it a bit cleaner) would be to use some expression magic:

另一个 hacky 解决方案(也许有人可以让它更干净一点)是使用一些表达魔法:

public class Example {

    public void CallingTest()
    {
        MethodInfo method = GetMethod<Example>(x => x.Test<object>());
        MethodInfo genericMethod = method.MakeGenericMethod(typeof (string));
        genericMethod.Invoke(this, null);

    }

    public static MethodInfo GetMethod<T>(Expression<Action<T>> expr)
    {
        return ((MethodCallExpression) expr.Body)
            .Method
            .GetGenericMethodDefinition();
    }

    public void Test<T>()
    {
        Console.WriteLine(typeof (T).Name);
    }
}

Note passing the 'object' type identifier as a generic type argument in the lambda. Couldn't figure out so quickly how to get around that. Either way, this is compile-time safe I think. It just feels wrong somehow :/

请注意在 lambda 中将“对象”类型标识符作为泛型类型参数传递。无法这么快地想出如何解决这个问题。无论哪种方式,我认为这是编译时安全的。不知何故感觉不对:/

回答by JaredPar

This approach will not work. The reason why is that Type is an object who's type is determined at runtime. However you are trying to use it to call a generic method. A generic method call's type is established at compile time. Hence a Type object can't ever be used for a type parameter on a generic method.

这种方法是行不通的。原因是 Type 是一个在运行时确定类型的对象。但是,您正在尝试使用它来调用通用方法。泛型方法调用的类型是在编译时建立的。因此,Type 对象永远不能用于泛型方法的类型参数。

回答by Jon Skeet

You need to use reflection, unfortunately (for the reasons Jared mentioned). For example:

不幸的是,您需要使用反射(出于 Jared 提到的原因)。例如:

MethodInfo method = typeof(Foo).GetMethod("MyGenericMethod");
method = method.MakeGenericMethod(t);
method.Invoke(this, new object[0]);

Obviously you'd want more error checking in reality :)

显然,您希望在现实中进行更多错误检查:)



Side note: my local MSDN doesn't specify that the parameter from MakeGenericMethod is a parameter array, so I'd have expected to require:

旁注:我的本地 MSDN 没有指定来自 MakeGenericMethod 的参数是一个参数数组,所以我希望需要:

method = method.MakeGenericMethod(new Type[] { t });

but it seems it isa parameter array in reality, and the online MSDN docsagree. Odd.

但它似乎现实中的参数数组,在线 MSDN 文档也同意。奇怪的。