有没有办法获得typeof Func <T,bool>?

Sel*_*enç 8 c# generics reflection

精简版 :

我们可以Func<T,T>使用以下类型:

typeof(Func<,>) 
Run Code Online (Sandbox Code Playgroud)

但是,如果我想获得类型Func<T, bool>,我应该使用什么,或者可以做什么呢?显然,这不编译:

typeof(Func<, bool>)
Run Code Online (Sandbox Code Playgroud)

长版:

考虑以下场景,我有两个类似的方法,我想Func<T, int>使用Reflection 得到第二个():

public void Foo<T>(Func<T, bool> func) { }

public void Foo<T>(Func<T, int> func) { }
Run Code Online (Sandbox Code Playgroud)

我正在尝试这个:

 var methodFoo = typeof (Program)
            .GetMethods()
            .FirstOrDefault(m => m.Name == "Foo" &&
                        m.GetParameters()[0]
                        .ParameterType
                        .GetGenericTypeDefinition() == typeof (Func<,>));
Run Code Online (Sandbox Code Playgroud)

但是,由于的泛型类型定义Func<T, bool>Func<T, int>相等,它给我的第一个方法.要解决这个问题,我可以执行以下操作:

var methodFoo = typeof (Program)
            .GetMethods()
            .FirstOrDefault(m => m.Name == "Foo" &&
                        m.GetParameters()[0]
                        .ParameterType
                        .GetGenericArguments()[1] == typeof(int));
Run Code Online (Sandbox Code Playgroud)

然后我得到了正确的方法,但我不喜欢这种方式.对于更复杂的情况,这似乎是一种开销.我想要做的是Func<T,bool>在上面的失败尝试中得到类似的类型,然后我可以使用这个重载而不是使用Linq ,GetMethod并执行以下操作:

var methodFoo = typeof (Program)
            .GetMethod("Foo", 
            BindingFlags.Public | BindingFlags.Instance,
            null, 
            new[] {typeof (Func<, bool>)}, // ERROR typeof(Func<,>) doesn't work either
            null);
Run Code Online (Sandbox Code Playgroud)

注意:Ofcourse Func<T,T>只是一个例子,问题不是特定于任何类型.

das*_*ght 5

不幸的是,您无法System.Type为部分绑定的泛型类型构建对象.你这样做的方式(即使用GetGenericArguments()[1] == typeof(int))是正确的方法.

如果需要在多个位置重用它,可以构建一个辅助扩展方法,该方法接受泛型类型定义和一个System.Type对象数组,true如果匹配则返回:

static bool IsGenericInstance(this Type t, Type genTypeDef, params Type[] args) {
    if (!t.IsGenericType) return false;
    if (t.GetGenericTypeDefinition() != genTypeDef) return false;
    var typeArgs = t.GetGenericArguments();
    if (typeArgs.Length != args.Length) return false;
    // Go through the arguments passed in, interpret nulls as "any type"
    for (int i = 0 ; i != args.Length ; i++) {
        if (args[i] == null) continue;
        if (args[i] != typeArgs[i]) return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

现在您可以像这样重写代码:

var methodFoo = typeof (Program)
    .GetMethods()
    .FirstOrDefault(m => m.Name == "Foo" &&
        m.GetParameters()[0]
            .ParameterType
            .IsGenericInstance(typeof(Func<,>), null, typeof(bool))
    );
Run Code Online (Sandbox Code Playgroud)

如果我使用methodFoo.GetParameters()[0].ParameterType,我得到的类型,Func<T, int>所以它肯定是在某处建造的

T上面的类型是泛型方法的泛型类型参数Foo.由于它不是"任何类型",如果您愿意,可以构造此类型:

var typeT = methodFoo.GetGenericArguments()[0];
var funcTbool = typeof(Func<,>).MakeGenericType(typeT, typeof(bool));
Run Code Online (Sandbox Code Playgroud)

catch是typeT绑定到特定泛型方法的,使得该funcTbool类型不适合跨多个独立泛型方法进行搜索.

如果T是方法所属类的类型参数,请说

class FooType<T> {
    public void Foo(Func<T, bool> func) { }
    public void Foo(Func<T, int> func) { }
}
Run Code Online (Sandbox Code Playgroud)

您将能够构建funcTbool基于FooType<>的泛型类型参数,并在不同Foo(...)方法的签名中搜索它.