【问题标题】:Identify Func<> parameter in method using reflection使用反射识别方法中的 Func<> 参数
【发布时间】:2021-07-28 01:49:43
【问题描述】:

我有一组方法,我想找出任何包含Func&lt;(,,,)&gt; 参数的方法(最好通过反射)。

通过使用 [IsFuncAttribute] 标记这些参数就足够简单了,但如果可能的话,我想避免这种方法。

例如,如果我有以下方法,如何可靠地确定第三个参数是Func&lt;,&gt;

public T MyMethod<T>(T param1, bool param2, Func<t,bool> param3)
{
    // do something
}

另外,能够将第三个参数识别为具有非 void 返回类型的委托同样有用。

【问题讨论】:

  • 从拥有方法的类的类型中,您可以get the methodsMethodInfo.GetParameters() 为您获取一个 ParameterInfo 数组,其中包含参数的类型信息。
  • 一般来说,如果你在特定方法的代码中,你就会知道它的函数签名。像您这样的函数 (public T MyMethod&lt;T&gt;(T param1, bool param2, Func&lt;t,bool&gt; param3)) 的第三个参数将始终是 Func&lt;t,bool&gt;。你想做什么? (为什么?)

标签: c# reflection func


【解决方案1】:
MethodInfo methodInfo = ...;
ParameterInfo[] parameters = methodInfo.GetParameters();

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

DotNetFiddle

这是专门针对Func&lt;,&gt; 的。如果您想匹配任何类型的 Func,具有任意数量的参数,那么您需要typeof(Func&lt;&gt;)typeof(Func&lt;,&gt;)typeof(Func&lt;,,&gt;) 等列表,或者您需要匹配全名的类型。

【讨论】:

  • 漂亮,正是我所追求的,谢谢@canton7。我试图比较ParameterTypeParameterType.UnderlyingSystemType,但似乎都没有给出与Func&lt;,&gt; 相等的类型
【解决方案2】:

如果您需要将 Func 与任意数量的参数匹配,作为对每个 Func 版本(其中有 17 个)进行显式测试的替代方法,您可以使用类似这种扩展方法的方法(请注意,这个特定示例是特定于 .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;
}

编辑:

虽然,如果您要经常进行此检查,上述方法可能不够高效。在这种情况下,您可能希望明确列出每个可能的 Func。但是,如果您按参数计数对它们进行索引,则实际上不需要全部检查它们:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 1970-01-01
    • 2011-01-13
    相关资源
    最近更新 更多