C# 如何使用反射来调用泛型方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/232535/
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-03 19:10:33  来源:igfitidea点击:

How do I use reflection to call a generic method?

c#.netgenericsreflection

提问by Bevan

What's the best way to call a generic method when the type parameter isn't known at compile time, but instead is obtained dynamically at runtime?

当类型参数在编译时未知,而是在运行时动态获取时,调用泛型方法的最佳方法是什么?

Consider the following sample code - inside the Example()method, what's the most concise way to invoke GenericMethod<T>()using the Typestored in the myTypevariable?

考虑以下示例代码 - 在Example()方法内部,GenericMethod<T>()使用Type存储在myType变量中的调用的最简洁方法是什么?

public class Sample
{
    public void Example(string typeName)
    {
        Type myType = FindType(typeName);

        // What goes here to call GenericMethod<T>()?
        GenericMethod<myType>(); // This doesn't work

        // What changes to call StaticMethod<T>()?
        Sample.StaticMethod<myType>(); // This also doesn't work
    }

    public void GenericMethod<T>()
    {
        // ...
    }

    public static void StaticMethod<T>()
    {
        //...
    }
}

采纳答案by Jon Skeet

You need to use reflection to get the method to start with, then "construct" it by supplying type arguments with MakeGenericMethod:

您需要使用反射来获取开始的方法,然后通过使用MakeGenericMethod提供类型参数来“构造”它:

MethodInfo method = typeof(Sample).GetMethod(nameof(Sample.GenericMethod));
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(this, null);

For a static method, pass nullas the first argument to Invoke. That's nothing to do with generic methods - it's just normal reflection.

对于静态方法,null作为第一个参数传递给Invoke. 这与泛型方法无关——它只是普通的反射。

As noted, a lot of this is simpler as of C# 4 using dynamic- if you can use type inference, of course. It doesn't help in cases where type inference isn't available, such as the exact example in the question.

如前所述,从 C# 4 开始,使用 C# 4 时其中很多都更简单dynamic- 当然,如果您可以使用类型推断。在类型推断不可用的情况下,它没有帮助,例如问题中的确切示例。

回答by Adrian Gallero

Just an addition to the original answer. While this will work:

只是对原始答案的补充。虽然这会起作用:

MethodInfo method = typeof(Sample).GetMethod("GenericMethod");
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(this, null);

It is also a little dangerous in that you lose compile-time check for GenericMethod. If you later do a refactoring and rename GenericMethod, this code won't notice and will fail at run time. Also, if there is any post-processing of the assembly (for example obfuscating or removing unused methods/classes) this code might break too.

这也有点危险,因为您会丢失GenericMethod. 如果您稍后进行重构和重命名GenericMethod,则此代码不会注意到并且会在运行时失败。此外,如果对程序集进行任何后处理(例如混淆或删除未使用的方法/类),此代码也可能会中断。

So, if you know the method you are linking to at compile time, and this isn't called millions of times so overhead doesn't matter, I would change this code to be:

因此,如果您知道在编译时链接到的方法,并且这不会被调用数百万次,因此开销无关紧要,我会将这段代码更改为:

Action<> GenMethod = GenericMethod<int>;  //change int by any base type 
                                          //accepted by GenericMethod
MethodInfo method = this.GetType().GetMethod(GenMethod.Method.Name);
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(this, null);

While not very pretty, you have a compile time reference to GenericMethodhere, and if you refactor, delete or do anything with GenericMethod, this code will keep working, or at least break at compile time (if for example you remove GenericMethod).

虽然不是很漂亮,但你有一个编译时参考GenericMethodhere,如果你重构、删除或使用 做任何事情GenericMethod,这段代码将继续工作,或者至少在编译时中断(例如,如果你删除了GenericMethod)。

Other way to do the same would be to create a new wrapper class, and create it through Activator. I don't know if there is a better way.

执行相同操作的其他方法是创建一个新的包装类,并通过Activator. 不知道有没有更好的办法。

回答by jbtule

With C# 4.0, reflection isn't necessary as the DLR can call it using runtime types. Since using the DLR library is kind of a pain dynamically (instead of the C# compiler generating code for you), the open source framework Dynamitey(.net standard 1.5) gives you easy cached run-time access to the same calls the compiler would generate for you.

在 C# 4.0 中,反射不是必需的,因为 DLR 可以使用运行时类型调用它。由于动态使用 DLR 库是一种痛苦(而不是 C# 编译器为您生成代码),因此开源框架Dynamitey(.net 标准 1.5)使您可以轻松缓存运行时访问编译器将生成的相同调用为你。

var name = InvokeMemberName.Create;
Dynamic.InvokeMemberAction(this, name("GenericMethod", new[]{myType}));


var staticContext = InvokeContext.CreateStatic;
Dynamic.InvokeMemberAction(staticContext(typeof(Sample)), name("StaticMethod", new[]{myType}));

回答by Mariusz Pawelski

Calling a generic method with a type parameter known only at runtime can be greatly simplified by using a dynamictype instead of the reflection API.

通过使用dynamic类型而不是反射 API,可以大大简化使用仅在运行时已知的类型参数来调用泛型方法。

To use this technique the type must be known from the actual object (not just an instance of the Typeclass). Otherwise, you have to create an object of that type or use the standard reflection API solution. You can create an object by using the Activator.CreateInstancemethod.

要使用此技术,必须从实际对象(而不仅仅是Type类的实例)知道类型。否则,您必须创建该类型的对象或使用标准反射 API解决方案。您可以使用Activator.CreateInstance方法创建对象。

If you want to call a generic method, that in "normal" usage would have had its type inferred, then it simply comes to casting the object of unknown type to dynamic. Here's an example:

如果你想调用一个泛型方法,在“正常”用法中会推断出它的类型,那么它只是将未知类型的对象强制转换为dynamic. 下面是一个例子:

class Alpha { }
class Beta { }
class Service
{
    public void Process<T>(T item)
    {
        Console.WriteLine("item.GetType(): " + item.GetType()
                          + "\ttypeof(T): " + typeof(T));
    }
}

class Program
{
    static void Main(string[] args)
    {
        var a = new Alpha();
        var b = new Beta();

        var service = new Service();
        service.Process(a); // Same as "service.Process<Alpha>(a)"
        service.Process(b); // Same as "service.Process<Beta>(b)"

        var objects = new object[] { a, b };
        foreach (var o in objects)
        {
            service.Process(o); // Same as "service.Process<object>(o)"
        }
        foreach (var o in objects)
        {
            dynamic dynObj = o;
            service.Process(dynObj); // Or write "service.Process((dynamic)o)"
        }
    }
}

And here's the output of this program:

这是这个程序的输出:

item.GetType(): Alpha    typeof(T): Alpha
item.GetType(): Beta     typeof(T): Beta
item.GetType(): Alpha    typeof(T): System.Object
item.GetType(): Beta     typeof(T): System.Object
item.GetType(): Alpha    typeof(T): Alpha
item.GetType(): Beta     typeof(T): Beta

Processis a generic instance method that writes the real type of the passed argument (by using the GetType()method) and the type of the generic parameter (by using typeofoperator).

Process是泛型实例方法,它写入传递参数的真实类型(通过使用GetType()方法)和泛型参数的类型(通过使用typeof运算符)。

By casting the object argument to dynamictype we deferred providing the type parameter until runtime. When the Processmethod is called with the dynamicargument then the compiler doesn't care about the type of this argument. The compiler generates code that at runtime checks the real types of passed arguments (by using reflection) and choose the best method to call. Here there is only this one generic method, so it's invoked with a proper type parameter.

通过将对象参数转换为dynamic类型,我们将提供类型参数推迟到运行时。当Process使用dynamic参数调用方法时,编译器不关心此参数的类型。编译器生成代码,在运行时检查传递参数的真实类型(通过使用反射)并选择调用的最佳方法。这里只有这一个泛型方法,所以它是用适当的类型参数调用的。

In this example, the output is the same as if you wrote:

在此示例中,输出与您编写的内容相同:

foreach (var o in objects)
{
    MethodInfo method = typeof(Service).GetMethod("Process");
    MethodInfo generic = method.MakeGenericMethod(o.GetType());
    generic.Invoke(service, new object[] { o });
}

The version with a dynamic type is definitely shorter and easier to write. You also shouldn't worry about performance of calling this function multiple times. The next call with arguments of the same type should be faster thanks to the cachingmechanism in DLR. Of course, you can write code that cache invoked delegates, but by using the dynamictype you get this behaviour for free.

带有动态类型的版本肯定更短更容易编写。您也不应该担心多次调用此函数的性能。由于DLR 中的缓存机制,使用相同类型参数的下一次调用应该更快。当然,您可以编写缓存调用委托的代码,但是通过使用dynamic类型,您可以免费获得这种行为。

If the generic method you want to call don't have an argument of a parametrized type (so its type parameter can't be inferred) then you can wrap the invocation of the generic method in a helper method like in the following example:

如果要调用的泛型方法没有参数化类型的参数(因此无法推断其类型参数),则可以将泛型方法的调用包装在辅助方法中,如下例所示:

class Program
{
    static void Main(string[] args)
    {
        object obj = new Alpha();

        Helper((dynamic)obj);
    }

    public static void Helper<T>(T obj)
    {
        GenericMethod<T>();
    }

    public static void GenericMethod<T>()
    {
        Console.WriteLine("GenericMethod<" + typeof(T) + ">");
    }
}

Increased type safety

提高类型安全性

What is really great about using dynamicobject as a replacement for using reflection API is that you only lose compile time checking of this particular type that you don't know until runtime. Other arguments and the name of the method are staticly analysed by the compiler as usual. If you remove or add more arguments, change their types or rename method name then you'll get a compile-time error. This won't happen if you provide the method name as a string in Type.GetMethodand arguments as the objects array in MethodInfo.Invoke.

使用dynamic对象代替使用反射 API 的真正好处在于,您只会丢失对这种特定类型的编译时检查,而这种检查直到运行时才知道。其他参数和方法名称由编译器照常静态分析。如果删除或添加更多参数、更改它们的类型或重命名方法名称,则会出现编译时错误。如果您将方法名称作为字符串提供,Type.GetMethod并将参数作为对象数组提供,则不会发生这种情况MethodInfo.Invoke

Below is a simple example that illustrates how some errors can be caught at compile time (commented code) and other at runtime. It also shows how the DLR tries to resolve which method to call.

下面是一个简单的例子,说明了如何在编译时(注释代码)和其他运行时捕获一些错误。它还显示了 DLR 如何尝试解析要调用的方法。

interface IItem { }
class FooItem : IItem { }
class BarItem : IItem { }
class Alpha { }

class Program
{
    static void Main(string[] args)
    {
        var objects = new object[] { new FooItem(), new BarItem(), new Alpha() };
        for (int i = 0; i < objects.Length; i++)
        {
            ProcessItem((dynamic)objects[i], "test" + i, i);

            //ProcesItm((dynamic)objects[i], "test" + i, i);
            //compiler error: The name 'ProcesItm' does not
            //exist in the current context

            //ProcessItem((dynamic)objects[i], "test" + i);
            //error: No overload for method 'ProcessItem' takes 2 arguments
        }
    }

    static string ProcessItem<T>(T item, string text, int number)
        where T : IItem
    {
        Console.WriteLine("Generic ProcessItem<{0}>, text {1}, number:{2}",
                          typeof(T), text, number);
        return "OK";
    }
    static void ProcessItem(BarItem item, string text, int number)
    {
        Console.WriteLine("ProcessItem with Bar, " + text + ", " + number);
    }
}

Here we again execute some method by casting the argument to the dynamictype. Only verification of first argument's type is postponed to runtime. You will get a compiler error if the name of the method you're calling doesn't exist or if other arguments are invalid (wrong number of arguments or wrong types).

这里我们再次通过将参数转换为dynamic类型来执行一些方法。只有第一个参数的类型的验证被推迟到运行时。如果您调用的方法的名称不存在或其他参数无效(参数数量错误或类型错误),您将收到编译器错误。

When you pass the dynamicargument to a method then this call is lately bound. Method overload resolution happens at runtime and tries to choose the best overload. So if you invoke the ProcessItemmethod with an object of BarItemtype then you'll actually call the non-generic method, because it is a better match for this type. However, you'll get a runtime error when you pass an argument of the Alphatype because there's no method that can handle this object (a generic method has the constraint where T : IItemand Alphaclass doesn't implement this interface). But that's the whole point. The compiler doesn't have information that this call is valid. You as a programmer know this, and you should make sure that this code runs without errors.

当您将dynamic参数传递给方法时,此调用是最近绑定的。方法重载解析发生在运行时并尝试选择最佳重载。因此,如果您ProcessItem使用BarItem类型对象调用该方法,那么您实际上将调用非泛型方法,因为它更适合此类型。但是,当您传递该Alpha类型的参数时,您将收到运行时错误,因为没有可以处理此对象的方法(泛型方法具有约束,where T : IItemAlpha类未实现此接口)。但这就是重点。编译器没有此调用有效的信息。作为程序员,您知道这一点,您应该确保此代码运行时没有错误。

Return type gotcha

返回类型陷阱

When you're calling a non-void method with a parameter of dynamic type, its return type will probably be dynamictoo. So if you'd change previous example to this code:

当你调用动态类型的参数的非空方法,它的返回类型可能dynamic。因此,如果您将前面的示例更改为此代码:

var result = ProcessItem((dynamic)testObjects[i], "test" + i, i);

then the type of the result object would be dynamic. This is because the compiler don't always know which method will be called. If you know the return type of the function call then you should implicitly convertit to the required type so the rest of the code is statically typed:

那么结果对象的类型将是dynamic. 这是因为编译器并不总是知道将调用哪个方法。如果您知道函数调用的返回类型,那么您应该隐式转换为所需的类型,以便其余代码是静态类型的:

string result = ProcessItem((dynamic)testObjects[i], "test" + i, i);

You'll get a runtime error if the type doesn't match.

如果类型不匹配,您将收到运行时错误。

Actually, if you try to get the result value in the previous example then you'll get a runtime error in the second loop iteration. This is because you tried to save the return value of a void function.

实际上,如果您尝试获取上一个示例中的结果值,那么您将在第二次循环迭代中遇到运行时错误。这是因为您试图保存 void 函数的返回值。

回答by Grax32

Adding on to Adrian Gallero's answer:

添加Adrian Gallero 的回答

Calling a generic method from type info involves three steps.

从类型信息调用泛型方法涉及三个步骤。

TLDR: Calling a known generic method with a type object can be accomplished by:

TLDR:可以通过以下方式使用类型对象调用已知的泛型方法:

((Action)GenericMethod<object>)
    .Method
    .GetGenericMethodDefinition()
    .MakeGenericMethod(typeof(string))
    .Invoke(this, null);

where GenericMethod<object>is the method name to call and any type that satisfies the generic constraints.

哪里GenericMethod<object>是要调用的方法名称以及满足泛型约束的任何类型。

(Action) matches the signature of the method to be called i.e. (Func<string,string,int>or Action<bool>)

(Action) 匹配要调用的方法的签名,即(Func<string,string,int>Action<bool>

Step 1 is getting the MethodInfo for the generic method definition

第 1 步是获取泛型方法定义的 MethodInfo

Method 1: Use GetMethod() or GetMethods() with appropriate types or binding flags.

方法 1:使用具有适当类型或绑定标志的 GetMethod() 或 GetMethods()。

MethodInfo method = typeof(Sample).GetMethod("GenericMethod");

Method 2: Create a delegate, get the MethodInfo object and then call GetGenericMethodDefinition

方法二:创建委托,获取MethodInfo对象,然后调用GetGenericMethodDefinition

From inside the class that contains the methods:

从包含方法的类内部:

MethodInfo method = ((Action)GenericMethod<object>)
    .Method
    .GetGenericMethodDefinition();

MethodInfo method = ((Action)StaticMethod<object>)
    .Method
    .GetGenericMethodDefinition();

From outside of the class that contains the methods:

从包含方法的类的外部:

MethodInfo method = ((Action)(new Sample())
    .GenericMethod<object>)
    .Method
    .GetGenericMethodDefinition();

MethodInfo method = ((Action)Sample.StaticMethod<object>)
    .Method
    .GetGenericMethodDefinition();

In C#, the name of a method, i.e. "ToString" or "GenericMethod" actually refers to a group of methods that may contain one or more methods. Until you provide the types of the method parameters, it is not known which method you are referring to.

在 C# 中,方法的名称,即“ToString”或“GenericMethod”实际上是指可能包含一个或多个方法的一组方法。在您提供方法参数的类型之前,不知道您指的是哪种方法。

((Action)GenericMethod<object>)refers to the delegate for a specific method. ((Func<string, int>)GenericMethod<object>)refers to a different overload of GenericMethod

((Action)GenericMethod<object>)指特定方法的委托。 ((Func<string, int>)GenericMethod<object>)指的是 GenericMethod 的不同重载

Method 3: Create a lambda expression containing a method call expression, get the MethodInfo object and then GetGenericMethodDefinition

方法 3:创建一个包含方法调用表达式的 lambda 表达式,获取 MethodInfo 对象,然后 GetGenericMethodDefinition

MethodInfo method = ((MethodCallExpression)((Expression<Action<Sample>>)(
    (Sample v) => v.GenericMethod<object>()
    )).Body).Method.GetGenericMethodDefinition();

This breaks down to

这分解为

Create a lambda expression where the body is a call to your desired method.

创建一个 lambda 表达式,其中主体是对所需方法的调用。

Expression<Action<Sample>> expr = (Sample v) => v.GenericMethod<object>();

Extract the body and cast to MethodCallExpression

提取主体并转换为 MethodCallExpression

MethodCallExpression methodCallExpr = (MethodCallExpression)expr.Body;

Get the generic method definition from the method

从方法中获取泛型方法定义

MethodInfo methodA = methodCallExpr.Method.GetGenericMethodDefinition();

Step 2 is calling MakeGenericMethod to create a generic method with the appropriate type(s).

第 2 步调用 MakeGenericMethod 以创建具有适当类型的泛型方法。

MethodInfo generic = method.MakeGenericMethod(myType);

Step 3 is invoking the method with the appropriate arguments.

第 3 步是使用适当的参数调用方法。

generic.Invoke(this, null);

回答by Thierry

This is my 2 cents based on Grax's answer, but with two parameters required for a generic method.

这是我的 2 美分基于Grax 的答案,但具有通用方法所需的两个参数。

Assume your method is defined as follows in an Helpers class:

假设您的方法在 Helpers 类中定义如下:

public class Helpers
{
    public static U ConvertCsvDataToCollection<U, T>(string csvData)
    where U : ObservableCollection<T>
    {
      //transform code here
    }
}

In my case, U type is always an observable collection storing object of type T.

就我而言,U 类型始终是 T 类型的可观察集合存储对象。

As I have my types predefined, I first create the "dummy" objects that represent the observable collection (U) and the object stored in it (T) and that will be used below to get their type when calling the Make

由于我已经预定义了类型,因此我首先创建了代表可观察集合 (U) 和存储在其中的对象 (T) 的“虚拟”对象,并且在调用 Make 时将在下面使用这些对象来获取它们的类型

object myCollection = Activator.CreateInstance(collectionType);
object myoObject = Activator.CreateInstance(objectType);

Then call the GetMethod to find your Generic function:

然后调用 GetMethod 来查找您的泛型函数:

MethodInfo method = typeof(Helpers).
GetMethod("ConvertCsvDataToCollection");

So far, the above call is pretty much identical as to what was explained above but with a small difference when you need have to pass multiple parameters to it.

到目前为止,上面的调用与上面解释的几乎相同,但是当您需要将多个参数传递给它时有一点不同。

You need to pass an Type[] array to the MakeGenericMethod function that contains the "dummy" objects' types that were create above:

您需要将 Type[] 数组传递给包含上面创建的“虚拟”对象类型的 MakeGenericMethod 函数:

MethodInfo generic = method.MakeGenericMethod(
new Type[] {
   myCollection.GetType(),
   myObject.GetType()
});

Once that's done, you need to call the Invoke method as mentioned above.

完成后,您需要调用上面提到的 Invoke 方法。

generic.Invoke(null, new object[] { csvData });

And you're done. Works a charm!

你已经完成了。很有魅力!

UPDATE:

更新:

As @Bevan highlighted, I do not need to create an array when calling the MakeGenericMethod function as it takes in params and I do not need to create an object in order to get the types as I can just pass the types directly to this function. In my case, since I have the types predefined in another class, I simply changed my code to:

正如@Bevan 所强调的那样,在调用 MakeGenericMethod 函数时我不需要创建数组,因为它需要参数,而且我不需要创建对象来获取类型,因为我可以直接将类型传递给这个函数。就我而言,由于我在另一个类中预定义了类型,因此我只需将代码更改为:

object myCollection = null;

MethodInfo method = typeof(Helpers).
GetMethod("ConvertCsvDataToCollection");

MethodInfo generic = method.MakeGenericMethod(
   myClassInfo.CollectionType,
   myClassInfo.ObjectType
);

myCollection = generic.Invoke(null, new object[] { csvData });

myClassInfo contains 2 properties of type Typewhich I set at run time based on an enum value passed to the constructor and will provide me with the relevant types which I then use in the MakeGenericMethod.

myClassInfo 包含Type我在运行时根据传递给构造函数的枚举值设置的2 个类型的属性,并将为我提供相关类型,然后我在 MakeGenericMethod 中使用这些类型。

Thanks again for highlighting this @Bevan.

再次感谢您强调这个@Bevan。

回答by Dimitre Novatchev

Nobody provided the "classic Reflection" solution, so here is a complete code example:

没有人提供“经典反射”解决方案,所以这里是一个完整的代码示例:

using System;
using System.Collections;
using System.Collections.Generic;

namespace DictionaryRuntime
{
    public class DynamicDictionaryFactory
    {
        /// <summary>
        /// Factory to create dynamically a generic Dictionary.
        /// </summary>
        public IDictionary CreateDynamicGenericInstance(Type keyType, Type valueType)
        {
            //Creating the Dictionary.
            Type typeDict = typeof(Dictionary<,>);

            //Creating KeyValue Type for Dictionary.
            Type[] typeArgs = { keyType, valueType };

            //Passing the Type and create Dictionary Type.
            Type genericType = typeDict.MakeGenericType(typeArgs);

            //Creating Instance for Dictionary<K,T>.
            IDictionary d = Activator.CreateInstance(genericType) as IDictionary;

            return d;

        }
    }
}

The above DynamicDictionaryFactoryclass has a method

上面的DynamicDictionaryFactory类有一个方法

CreateDynamicGenericInstance(Type keyType, Type valueType)

CreateDynamicGenericInstance(Type keyType, Type valueType)

and it creates and returns an IDictionary instance, the types of whose keys and values are exactly the specified on the call keyTypeand valueType.

它创建并返回一个 IDictionary 实例,其键和值的类型与调用keyTypevalueType.

Here is a complete examplehow to call this method to instantiate and use a Dictionary<String, int>:

这是一个完整的示例,如何调用此方法来实例化和使用Dictionary<String, int>

using System;
using System.Collections.Generic;

namespace DynamicDictionary
{
    class Test
    {
        static void Main(string[] args)
        {
            var factory = new DictionaryRuntime.DynamicDictionaryFactory();
            var dict = factory.CreateDynamicGenericInstance(typeof(String), typeof(int));

            var typedDict = dict as Dictionary<String, int>;

            if (typedDict != null)
            {
                Console.WriteLine("Dictionary<String, int>");

                typedDict.Add("One", 1);
                typedDict.Add("Two", 2);
                typedDict.Add("Three", 3);

                foreach(var kvp in typedDict)
                {
                    Console.WriteLine("\"" + kvp.Key + "\": " + kvp.Value);
                }
            }
            else
                Console.WriteLine("null");
        }
    }
}

When the above console application is executed, we get the correct, expected result:

当上面的控制台应用程序被执行时,我们得到了正确的、预期的结果:

Dictionary<String, int>
"One": 1
"Two": 2
"Three": 3

回答by Matt

Inspired by Enigmativity's answer- let's assume you have two (or more) classes, like

受到Enigmativity 答案的启发- 假设您有两个(或更多)类,例如

public class Bar { }
public class Square { }

and you want to call the method Foo<T>with Barand Square, which is declared as

并且您想Foo<T>使用Barand调用该方法Square,该方法声明为

public class myClass
{
    public void Foo<T>(T item)
    {
        Console.WriteLine(typeof(T).Name);
    }
}

Then you can implement an Extension methodlike:

然后你可以实现一个扩展方法,如:

public static class Extension
{
    public static void InvokeFoo<T>(this T t)
    {
        var fooMethod = typeof(myClass).GetMethod("Foo");
        var tType = typeof(T);
        var fooTMethod = fooMethod.MakeGenericMethod(new[] { tType });
        fooTMethod.Invoke(new myClass(), new object[] { t });
    }
}

With this, you can simply invoke Foolike:

有了这个,你可以简单地调用Foo

var objSquare = new Square();
objSquare.InvokeFoo();

var objBar = new Bar();
objBar.InvokeFoo();

which works for every class. In this case, it will output:

这适用于每个班级。在这种情况下,它将输出:

Square
Bar