c# - 如何检查 MethodInfo 是否匹配泛型 T 的委托(delegate),其中 T 是 Action 还是 Func?

标签 c# generics reflection delegates

问题如何检查MethodInfo是否匹配T类型的Delegate,其中TAction 还是 Func

代码示例,包含从 Assembly 中获取所有静态函数的用例,应该匹配 T 类型的 Delegate :

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 block 中。

最佳答案

您应该通过检查参数和返回类型来手动检查签名是否兼容。

例如,以下代码检查委托(delegate)方法的赋值兼容性。这不会将类型限制为 ActionFunc;它适用于任何委托(delegate)类型。

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 以检查它是否真的是委托(delegate)类型。我把这个留给你。

关于c# - 如何检查 MethodInfo 是否匹配泛型 T 的委托(delegate),其中 T 是 Action 还是 Func?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28353920/

相关文章:

java - java中的动态注释更改

c# - 如何单击网页中的按钮

c# - 如何从 PSD 文件获取 DPI

c# - 如何使用 C# 隐藏/显示进程?

swift - Swift 中集合类型的扩展,用于查找对象之后的所有对象

Java-使用泛型返回多个类型

c# - 为什么我需要 'dummy' 行代码才能加载PresentationFramework?

java - <?扩展类> 和 <? Java 中的 super Class> - 为什么它会这样工作?

c# - 通过特定属性过滤类实例的属性并调用属性的方法

c# - 如何通过反射过滤任何属性的集合?