如何检查 MethodInfo 是否匹配泛型 T 的委托,其中 T 是 Action 还是 Func?
How to check that MethodInfo matches Delegate of generic type T, where T is either Action or Func?
问题: 如何检查 MethodInfo
匹配 T
类型的 Delegate
,其中 T
是 Action
或 Func
?
代码示例,包含从 Assembly
中获取所有静态函数的用例, 应该 匹配 Delegate
类型 T
:
void AddScriptFunctions<T>(Assembly assembly, Dictionary<string, T> funMap) where T: class
{
foreach(Type type in assembly.GetTypes())
{
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
foreach(MethodInfo method in methods)
{
// How to check that MethodInfo can be converted into delegate of type T
// where T is Func<...> or Action<...>
if( ........ )
{
var function = (T)(object)Delegate.CreateDelegate(typeof(T), method);
funMap.Add(method.Name.ToLower(), function);
}
}
}
函数调用示例:
var functions = new Dictionary<string, Func<int, int>>();
AddScriptFunctions(Assembly.GetExecutingAssembly(), functions);
var functions2 = new Dictionary<string, Action>();
AddScriptFunctions(Assembly.GetExecutingAssembly(), functions2);
注意:没有将 Delegate.CreateDelegate
包含在 try/catch 块中。
您应该通过检查参数和 return 类型手动检查签名是否兼容。
例如,以下代码检查要委托的方法的分配兼容性。这不会将类型限制为 Action
或 Func
;它适用于任何委托类型。
private void AddScriptFunctions<T>(Assembly assembly, Dictionary<string, T> funMap) where T : class
{
foreach (Type type in assembly.GetTypes())
{
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
foreach (MethodInfo method in methods)
{
if (IsMethodCompatibleWithDelegate<T>(method)))
{
var function = (T) (object) Delegate.CreateDelegate(typeof (T), method);
funMap.Add(method.Name.ToLower(), function);
}
}
}
}
public bool IsMethodCompatibleWithDelegate<T>(MethodInfo method) where T : class
{
Type delegateType = typeof(T);
MethodInfo delegateSignature = delegateType.GetMethod("Invoke");
bool parametersEqual = delegateSignature
.GetParameters()
.Select(x => x.ParameterType)
.SequenceEqual(method.GetParameters()
.Select(x => x.ParameterType));
return delegateSignature.ReturnType == method.ReturnType &&
parametersEqual;
}
当然这段代码没有考虑逆变;如果您需要它以逆变方式工作,您需要检查参数是否兼容赋值,而不仅仅是等于(就像我所做的那样)。
按照防御性编程实践,您可能需要验证类型参数 T
以检查它是否真的是委托类型。这个交给你了。
问题: 如何检查 MethodInfo
匹配 T
类型的 Delegate
,其中 T
是 Action
或 Func
?
代码示例,包含从 Assembly
中获取所有静态函数的用例, 应该 匹配 Delegate
类型 T
:
void AddScriptFunctions<T>(Assembly assembly, Dictionary<string, T> funMap) where T: class
{
foreach(Type type in assembly.GetTypes())
{
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
foreach(MethodInfo method in methods)
{
// How to check that MethodInfo can be converted into delegate of type T
// where T is Func<...> or Action<...>
if( ........ )
{
var function = (T)(object)Delegate.CreateDelegate(typeof(T), method);
funMap.Add(method.Name.ToLower(), function);
}
}
}
函数调用示例:
var functions = new Dictionary<string, Func<int, int>>();
AddScriptFunctions(Assembly.GetExecutingAssembly(), functions);
var functions2 = new Dictionary<string, Action>();
AddScriptFunctions(Assembly.GetExecutingAssembly(), functions2);
注意:没有将 Delegate.CreateDelegate
包含在 try/catch 块中。
您应该通过检查参数和 return 类型手动检查签名是否兼容。
例如,以下代码检查要委托的方法的分配兼容性。这不会将类型限制为 Action
或 Func
;它适用于任何委托类型。
private void AddScriptFunctions<T>(Assembly assembly, Dictionary<string, T> funMap) where T : class
{
foreach (Type type in assembly.GetTypes())
{
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
foreach (MethodInfo method in methods)
{
if (IsMethodCompatibleWithDelegate<T>(method)))
{
var function = (T) (object) Delegate.CreateDelegate(typeof (T), method);
funMap.Add(method.Name.ToLower(), function);
}
}
}
}
public bool IsMethodCompatibleWithDelegate<T>(MethodInfo method) where T : class
{
Type delegateType = typeof(T);
MethodInfo delegateSignature = delegateType.GetMethod("Invoke");
bool parametersEqual = delegateSignature
.GetParameters()
.Select(x => x.ParameterType)
.SequenceEqual(method.GetParameters()
.Select(x => x.ParameterType));
return delegateSignature.ReturnType == method.ReturnType &&
parametersEqual;
}
当然这段代码没有考虑逆变;如果您需要它以逆变方式工作,您需要检查参数是否兼容赋值,而不仅仅是等于(就像我所做的那样)。
按照防御性编程实践,您可能需要验证类型参数 T
以检查它是否真的是委托类型。这个交给你了。