c# - 有没有办法得到 typeof Func<T, bool>?

标签 c# generics reflection

简短版:

我们可以得到typeof Func<T,T>使用:

typeof(Func<,>) 

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

typeof(Func<, bool>)

长版:

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

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

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

我正在尝试这个:

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

但是由于Func<T, bool>的泛型类型定义|和 Func<T, int>是平等的,它给了我第一种方法。要解决此问题,我可以执行以下操作:

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

然后我得到了正确的方法,但我不喜欢这种方式。对于更复杂的情况,这似乎是一种开销。我想要做的是获取 Func<T,bool> 的类型就像我上面失败的尝试一样,我可以使用 this overload 而不是使用 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);

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

最佳答案

不幸的是,您无法构建 System.Type部分绑定(bind)泛型类型的对象。你这样做的方式(即使用 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;
}

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

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

if I use methodFoo.GetParameters()[0].ParameterType, I'm getting the type of Func<T, int> so it is definitely being constructed somewhere

类型T以上是你的泛型方法的泛型类型参数 Foo .由于它不是“任何类型”,因此您可以根据需要构造此类型:

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

要注意的是 typeT绑定(bind)到特定的泛型方法,使得 funcTbool类型不适合跨多个独立的泛型方法进行搜索。

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

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

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

关于c# - 有没有办法得到 typeof Func<T, bool>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25148028/

相关文章:

c# - 读取方法属性的值

java - 什么时候使用反射是一种好的做法?

c# - 使用反射 (DotNET) 在程序集中查找所有命名空间

javascript - 几个正则表达式查询

c# - 用户控件的可见属性何时会影响其子项?

java - String 类无法转换为 Node 类

java - Java 中的泛型——实现接口(interface)

ios - 引用泛型类型 'Map' 需要 <...> 中的参数 - Swift

c# - FileStream 与/差异 StreamWriter?

java - 使用 Java 反射仅获取类的公共(public)方法