使用反射识别方法中的 Func<> 参数
Identify Func<> parameter in method using reflection
我有一组方法,我想找出任何包含 Func<(,,,)>
参数的方法(最好通过反射)。
通过使用 [IsFuncAttribute] 标记这些参数就足够简单了,但我想尽可能避免这种方法。
例如,如果我有下面的方法,我如何可靠地确定第三个参数是一个Func<,>
?
public T MyMethod<T>(T param1, bool param2, Func<t,bool> param3)
{
// do something
}
或者,能够将第三个参数标识为具有非 void return 类型的委托同样有用。
MethodInfo methodInfo = ...;
ParameterInfo[] parameters = methodInfo.GetParameters();
bool thirdParameterIsFunc =
parameters.Length >= 3 &&
parameters[2].ParameterType.IsGenericType &&
parameters[2].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>));
这是专门针对 Func<,>
的。如果你想用任意数量的参数匹配任何类型的 Func,那么你要么需要 typeof(Func<>)
、typeof(Func<,>)
、typeof(Func<,,>)
等列表,要么你需要匹配类型的全名。
如果您需要将 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];
}
我有一组方法,我想找出任何包含 Func<(,,,)>
参数的方法(最好通过反射)。
通过使用 [IsFuncAttribute] 标记这些参数就足够简单了,但我想尽可能避免这种方法。
例如,如果我有下面的方法,我如何可靠地确定第三个参数是一个Func<,>
?
public T MyMethod<T>(T param1, bool param2, Func<t,bool> param3)
{
// do something
}
或者,能够将第三个参数标识为具有非 void return 类型的委托同样有用。
MethodInfo methodInfo = ...;
ParameterInfo[] parameters = methodInfo.GetParameters();
bool thirdParameterIsFunc =
parameters.Length >= 3 &&
parameters[2].ParameterType.IsGenericType &&
parameters[2].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>));
这是专门针对 Func<,>
的。如果你想用任意数量的参数匹配任何类型的 Func,那么你要么需要 typeof(Func<>)
、typeof(Func<,>)
、typeof(Func<,,>)
等列表,要么你需要匹配类型的全名。
如果您需要将 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];
}