简体   繁体   中英

Identify Func<> parameter in method using reflection

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.

MethodInfo methodInfo = ...;
ParameterInfo[] parameters = methodInfo.GetParameters();

bool thirdParameterIsFunc =
    parameters.Length >= 3 &&
    parameters[2].ParameterType.IsGenericType &&
    parameters[2].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>));

DotNetFiddle

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.

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];
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM