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