检索泛型方法的正确重载的MethodInfo

时间:2010-12-14 19:34:18

标签: c# .net generics reflection

我有这种类型,包含泛型方法的两个重载。我喜欢使用反射检索其中一个重载(使用Func<T>参数)。但问题是我无法找到正确的参数类型来为Type.GetMethod(string, Type[])方法提供。

这是我的班级定义:

public class Foo
{
    public void Bar<T>(Func<T> f) { }
    public void Bar<T>(Action<T> a) { }
}

这就是我想出来的,遗憾的是没有成功:

[TestMethod]
public void Test1()
{
    Type parameterType = typeof(Func<>);

    var method = typeof(Foo).GetMethod("Bar", new Type[] { parameterType });

    Assert.IsNotNull(method); // Fails
}

如何获得我知道参数的通用方法的MethodInfo

5 个答案:

答案 0 :(得分:9)

答案 1 :(得分:4)

令人惊讶的是,看起来您需要调用GetMethods()并循环使用这些方法,直到找到所需的方法。

例如:

var yourMethod = typeof(Foo).GetMethods()
    .First(m => m.Name == "Bar" 
             && m.GetParameters().Length == 1
             && m.GetParameters()[0].ParameterType.ContainsGenericParameters
             && m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Func<>));

答案 2 :(得分:1)

您需要使用MethodInfo.MakeGenericMethod.

指定具体类型

但是,我应该指出,当你有一个重载的泛型方法时,获取正确的类型来调用MakeGenericMethod并不容易。

以下是一个例子:

var method = typeof(Foo)
                 .GetMethods()
                 .Where(x => x.Name == "Bar")
                 .Where(x => x.IsGenericMethod)
                 .Where(x => x.GetGenericArguments().Length == 1)
                 .Where(x => x.GetParameters().Length == 1)
                 .Where(x => 
                     x.GetParameters()[0].ParameterType == 
                     typeof(Action<>).MakeGenericType(x.GetGenericArguments()[0])
                 )
                 .Single();

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

 Foo foo = new Foo();
 method.Invoke(foo, new Func<int>[] { () => return 42; });

答案 3 :(得分:1)

我不你可以使用GetMethod直接做到这一点。我怀疑你必须迭代所有名为Bar的方法,然后:

  • 检查方法是否有一个类型参数
  • 检查方法是否有一个普通参数
  • 使用type参数创建Func<T>typeof(Func<>).MakeGenericType),并检查参数类型是否匹配。

LINQ对这类事情有好处。完整样本:

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

public class Foo
{
    public void Bar<T>(Func<T> f) { }
    public void Bar<T>(Action<T> a) { }
}

class Test
{
    static void Main()
    {
        var methods = from method in typeof(Foo).GetMethods()
                      where method.Name == "Bar"
                      let typeArgs = method.GetGenericArguments()
                      where typeArgs.Length == 1
                      let parameters = method.GetParameters()
                      where parameters.Length == 1
                      where parameters[0].ParameterType == 
                            typeof(Func<>).MakeGenericType(typeArgs[0])
                      select method;

        Console.WriteLine("Matching methods...");
        foreach (var method in methods)
        {
            Console.WriteLine(method);
        }
    }
}

基本上,仿制药和反思在组合中真的很讨厌,我担心:(

答案 4 :(得分:0)

你只需要使用GetMethod就可以解决问题 - 你可以尝试一些方法;

var method = (from m in typeof(Foo).GetMethods()
  where
    m.IsGenericMethodDefinition == true &&
    m.Name == "Bar" &&
    m.GetParameters().Length > 0 &&
    m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == parameterType
  select m).FirstOrDefault();