c# - 如何区分泛型类中具有相同名称和参数个数的两个方法?

标签 c# generics reflection

这是我的类(class):

public class MyClass<T>
{
    public void MyMethod(T a)
    {
    }

    public void MyMethod(int a)
    {
    }
}

即使 int 是通用类型参数,我如何使用 Reflection Invoke MyMethod(T) MyClass?

这里有一条语句可以做到这一点(可能效率低下,但我喜欢简洁):

var mc = new MyClass<int>();

typeof(MyClass<int>).GetMethods().ElementAt(
    typeof(MyClass<int>).
    GetGenericTypeDefinition().
    GetMethods().ToList().FindIndex(m =>
        m.Name.Equals("MyMethod") && 
        m.GetParameters().Count() == 1 &&
        m.GetParameters()[0].ParameterType.IsGenericParameter)
    ).Invoke(mc, new object[] { 1 });

最佳答案

修改后的答案

好的,所以我想我已经弄清楚为什么 IsGenericParameter属性评估为 false 是因为您正在为 <T> 创建具有显式类型的 MyClass 类型.

因为编译器新什么类型a参数是(从类的实例化推断),我猜测编译器将参数视为非泛型类型。

此外,根据我在 MSDN 中阅读的内容,我认为 ParameterType.IsGenericParameterType.IsGenericType property只会评估为真 每当你有像 MyMethod<T>() 这样的方法时与 MyMethod(T a) ,其中 <T> 的类型从用类实例化的类型推断出来。

下面是一个演示这个的小程序:

using System;
using System.Linq;
using System.Reflection;

namespace GenericParametersViaReflectionTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // Note: we're using the type without specifying a type for <T>.
            var classType = typeof(MyClass<>);

            foreach (MethodInfo method in classType.GetMembers()
                .Where(method => method.Name == "MyMethod"))
            {
                // Iterate through each parameter of the method
                foreach (var param in method.GetParameters())
                {
                    // For generic methods, the name will be "T" and the FullName
                    // will be null; you can use which ever check you prefer.
                    if (param.ParameterType.Name == "T"
                        || param.ParameterType.FullName == null)
                        Console.WriteLine("We found our generic method!");
                    else
                        Console.WriteLine("We found the non-generic method:");

                    Console.WriteLine("Method Name: {0}", method.Name);
                    Console.WriteLine("Parameter Name: {0}", param.Name);
                    Console.WriteLine("Type: {0}", param.ParameterType.Name);
                    Console.WriteLine("Type Full Name: {0}",
                        param.ParameterType.FullName ?? "null");
                    Console.WriteLine("");
                }   
            }
            Console.Read();
        }
    }
    public class MyClass<T>
    {
        public void MyMethod(T a) { }
        public void MyMethod(int a) { }
    }
}

我们最终得到的结果是:

We found or generic method!
Method Name: MyMethod
Parameter Name: a
Type: T
Type Full Name: null

We found the non-generic method:
Method Name: MyMethod
Parameter Name: a
Type: Int32
Type Full Name: System.Int32

如果您需要使用特定类型创建类的实例,您可能会发现 Activator.CreateInstance class也很有用。


原始答案

我认为,如果您传入与显式设置方法之一匹配的相同数据类型的参数(例如 Int32 方法),那么编译器会自动选择该方法而不是接受通用参数的方法。否则,泛型方法将由编译器选择。

但是,如果您希望能够控制选择哪个方法,您可以修改每个方法以具有不同的参数名称,同时保持相同的签名,如下所示:

public class MyClass<T>
{
    public void MyMethod(T genericA) {}
    public void MyMethod(int intA) {}
}

然后,使用 named parameters ,您可以显式调用所需的方法,如下所示:

var foo = new MyClass<int>();
foo.MyMethod(genericA: 24); // This will call the "MyMethod" that only accepts <T>.
foo.MyMethod(intA: 19); // This will call the "MyMethod" that only accepts integers.

编辑

出于某种原因,在我的原始答案中我错过了您提到的使用反射的部分,但看起来我的原始答案可以与这些其他答案结合起来为您提供一个可行的解决方案:

关于c# - 如何区分泛型类中具有相同名称和参数个数的两个方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13215555/

相关文章:

go - 如何列出接口(interface)类型中的方法名称?

c# - 如何使用反射调用静态构造函数?

c# - 实现 "ReOrderable Collection"并将其保存到数据库的最佳方法

c# - 使用 Linq 根据 Values 自定义对象的属性过滤 Hashtable

java-用节点理解LinkedList面试题

c# - 反射和通用类型

c# - 将 ODataQuery 转换为 TableQuery 以使用 OData 查询 Azure 表存储

c# - Asp.net(查找 2 个日期之间的记录)仅向远程服务器显示错误并在本地主机中正常工作

java - 为什么这个通用作业不起作用?

ios - 按索引移动数组中的元素