如何区分generics类中具有相同名称和参数数量的两种方法?

这是我的class级:

public class MyClass { public void MyMethod(T a) { } public void MyMethod(int a) { } } 

即使intMyClass的generics类型参数,我如何使用Reflection Invoke MyMethod(T)

这是一个单一的声明(可能效率低下,但我喜欢简洁):

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

我能够做到这一点的唯一方法是使用带有IsGenericParameter GetGenericTypeDefinition 。 在generics类型定义中,一个方法将IsGenericParameter设置为参数的true。 但是,对于封闭类型,没有任何参数会将此视为真。 然后,您不能使用generics类型定义中的MethodInfo来调用该方法,因此我存储了索引并使用它来查找封闭类型中的相应MethodInfo

 public class Program { public static void Main(string[] args) { bool invokeGeneric = true; MyClass b = new MyClass(); var type = b.GetType().GetGenericTypeDefinition(); int index = 0; foreach(var mi in type.GetMethods().Where(mi => mi.Name == "MyMethod")) { if (mi.GetParameters()[0].ParameterType.IsGenericParameter == invokeGeneric) { break; } index++; } var method = b.GetType().GetMethods().Where(mi => mi.Name == "MyMethod").ElementAt(index); method.Invoke(b, new object[] { 1 }); } } public class MyClass { public void MyMethod(T a) { Console.WriteLine("In generic method"); } public void MyMethod(int a) { Console.WriteLine("In non-generic method"); } } 

修订后的答案

好的,所以我想我已经弄清楚为什么IsGenericParameter属性的计算结果为false是因为你创建的MyClass类型带有的显式类型。

由于编译器新增了a参数的类型(从类的实例化推断),我猜测编译器将参数视为非generics类型。

另外,根据我在MSDN中阅读的内容,我认为每当你有一个像MyMethod()MyMethod(T a)这样的方法时, ParameterType.IsGenericParameter和Type.IsGenericType属性只会求值为true。 的类型是从使用类实例化的类型推断出来的。

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

 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 . 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 { public void MyMethod(T a) { } public void MyMethod(int a) { } } } 

我们最终得出的结果是:

我们发现或通用的方法!
方法名称:MyMethod
参数名称:a
类型:T
输入全名:null

我们发现了非通用方法:
方法名称:MyMethod
参数名称:a
类型:Int32
键入全名:System.Int32

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


原始答案

我认为如果你传入一个与明确设置的方法之一匹配的相同数据类型的参数(例如Int32方法),那么编译器会自动选择那个接受generics参数的参数。 否则,编译器将选择generics方法。

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

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

然后,使用命名参数 ,您可以显式调用所需的方法,如下所示:

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

编辑

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

  • 通过reflection调用带有可选参数的方法
  • 如何获取方法参数的名称?