Short version :
We can get the typeof Func<T,T>
using:
typeof(Func<,>)
but what if I want to get the type of Func<T, bool>
, what should I use, or is it possible to do? Clearly this doesn't compile :
typeof(Func<, bool>)
Long version :
Consider the following scenario, I have two similar method and I want to get the second one (Func<T, int>
) using Reflection:
public void Foo<T>(Func<T, bool> func) { }
public void Foo<T>(Func<T, int> func) { }
I'm trying this:
var methodFoo = typeof (Program)
.GetMethods()
.FirstOrDefault(m => m.Name == "Foo" &&
m.GetParameters()[0]
.ParameterType
.GetGenericTypeDefinition() == typeof (Func<,>));
But since the generic type definition of Func<T, bool>
and Func<T, int>
are equal it gives me the first method. To fix this I can do the following:
var methodFoo = typeof (Program)
.GetMethods()
.FirstOrDefault(m => m.Name == "Foo" &&
m.GetParameters()[0]
.ParameterType
.GetGenericArguments()[1] == typeof(int));
Then I get the correct method but I do not like this way. And it seems like a overhead for more complex situations. What I want to do is get the type of Func<T,bool>
like in my failed attempt above, then instead of using Linq I can use this overload of GetMethod
and do something like the following:
var methodFoo = typeof (Program)
.GetMethod("Foo",
BindingFlags.Public | BindingFlags.Instance,
null,
new[] {typeof (Func<, bool>)}, // ERROR typeof(Func<,>) doesn't work either
null);
Note: Ofcourse Func<T,T>
is just an example, question is not specific to any type.
Unfortunately, you cannot build a System.Type
object for a partially bound generic type. The way that you do it (i.e. with GetGenericArguments()[1] == typeof(int)
) is the proper way of doing it.
If you need to re-use this in multiple places, you could build a helper extension method that takes a generic type definition and an array of System.Type
objects, and returns true
if there is a match:
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;
}
Now you can rewrite your code like this:
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 ofFunc<T, int>
so it is definitely being constructed somewhere
The type T
above is the generic type parameter of your generic method Foo
. Since it is not "any type", you could construct this type if you wish:
var typeT = methodFoo.GetGenericArguments()[0];
var funcTbool = typeof(Func<,>).MakeGenericType(typeT, typeof(bool));
The catch is that typeT
is bound to the specific generic method, making the funcTbool
type not suitable for searching across multiple independent generic methods.
If T
were a type argument of the class to which the method belongs, say
class FooType<T> {
public void Foo(Func<T, bool> func) { }
public void Foo(Func<T, int> func) { }
}
you would be able to construct a funcTbool
based on FooType<>
's generic type parameter, and search for it in the signatures of the different Foo(...)
methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With