Reputation: 38
I have a collection of methods, and I'd like to identify any that contain a Func<(,,,)>
parameter (ideally through reflection).
This would be simple enough by tagging such parameters with [IsFuncAttribute], but I'd like to avoid that approach if possible.
For example, if I had the following method, how could I reliably determine that the third parameter is a Func<,>
?
public T MyMethod<T>(T param1, bool param2, Func<t,bool> param3)
{
// do something
}
Alternatively, being able to identify the third parameter as a delegate with a non void return type would be equally useful.
Upvotes: 1
Views: 915
Reputation: 3896
If you need to match a Func with any number of parameters, as an alternative to explicitly testing against every version of Func (There are 17 of them), you could use something like this extension method (Note that this particular example is specific to .NET Core/.Net 5.0):
public static bool IsAnyFunc(this Type type)
{
int typeParameterCount = type.GenericTypeArguments.Length;
if (typeParameterCount == 0)
{
return false;
}
Type funcType = typeof(Func<>)
.Assembly
.GetTypes()
.FirstOrDefault(t =>
t.Name.StartsWith("Func`")
&& t.GetTypeInfo().GenericTypeParameters.Length == typeParameterCount);
return funcType == null ? false : type.GetGenericTypeDefinition() == funcType;
}
Edit:
Although, if you're going to be making this check frequently, the above may not be performant enough. In which case you may want to explicitly list every possilbe Func. However, you don't actually need to check against them all, if you index them by parameter count:
private static readonly List<Type> FuncTypes = new()
{
typeof(Func<>),
typeof(Func<,>),
typeof(Func<,,>),
typeof(Func<,,,>),
typeof(Func<,,,,>),
typeof(Func<,,,,,>),
typeof(Func<,,,,,,>),
typeof(Func<,,,,,,,>),
typeof(Func<,,,,,,,,>),
typeof(Func<,,,,,,,,,>),
typeof(Func<,,,,,,,,,,>),
typeof(Func<,,,,,,,,,,,>),
typeof(Func<,,,,,,,,,,,,>),
typeof(Func<,,,,,,,,,,,,,>),
typeof(Func<,,,,,,,,,,,,,,>),
typeof(Func<,,,,,,,,,,,,,,,>),
typeof(Func<,,,,,,,,,,,,,,,,>)
};
public static bool IsAnyFunc(this Type type)
{
int typeParameterCount = type.GenericTypeArguments.Length;
if (typeParameterCount < 1 || typeParameterCount > FuncTypes.Count)
{
return false;
}
return type.GetGenericTypeDefinition() == FuncTypes[typeParameterCount - 1];
}
Upvotes: 2
Reputation: 42225
MethodInfo methodInfo = ...;
ParameterInfo[] parameters = methodInfo.GetParameters();
bool thirdParameterIsFunc =
parameters.Length >= 3 &&
parameters[2].ParameterType.IsGenericType &&
parameters[2].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>));
This is specifically for Func<,>
. If you want to match any sort of Func, with any number of parameters, then you'll either need a list of typeof(Func<>)
, typeof(Func<,>)
, typeof(Func<,,>)
, etc, or you'll need to match on the full name of the type.
Upvotes: 2