首页 > 解决方案 > 无法使用反射将方法组转换为非委托类型

问题描述

我正在尝试使用反射自动注册请求处理类。

这是手动添加处理程序以执行特定请求的示例。

// generic manual method of registration
server.RegisterHandler<GetData>(base.ExecuteMessage);

这是使用反射进行注册的尝试。调用方法将不接受 'ExecuteMessage' 方法,出现错误“错误 CS0428 无法将方法组 'ExecuteMessage' 转换为非委托类型 'object'。您是否打算调用该方法?”。

// registration with reflection
foreach (var type in serviceTypes)
{
    // registerHandlerMethod definition:    RegisterHandler<T>(Func<IMessage<T>, object> processMessageFn)
    // ExecuteMessage definition:           object ExecuteMessage(IMessage message)

    registerHandlerMethod.MakeGenericMethod(type).Invoke(server, new object[] { base.ExecuteMessage });
}

是否可以以任何方式强制转换 ExecuteMessage 方法以使其正常工作?

编辑:在下面添加了有问题的示例

class Program
{
    static void Main(string[] args)
    {
        var server = new Server();

        // generic manual method of registration
        server.RegisterHandler<GetData>(ExecuteMessage);

        // registration with reflection
        var serviceTypes = new List<Type> { typeof(GetData) };
        var registerHandlerMethod = typeof(Server).GetMethod(nameof(Server.RegisterHandler));

        foreach (var type in serviceTypes)
        {
            registerHandlerMethod.MakeGenericMethod(type).Invoke(server, new object[] { ExecuteMessage });
        }
    }

    static object ExecuteMessage(IMessage message)
    {
        return null;
    }

    internal class GetData
    {

    }

    internal interface IMessage<T> : IMessage
    {

    }

    internal interface IMessage
    {

    }

    internal class Server
    {

        internal void RegisterHandler<T>(Func<IMessage<T>, object> processMessageFn)
        {
        }
    }
}

标签: c#reflection

解决方案


“无法转换方法组...”的原因是因为编译器不知道要将其转换为的委托的类型。

您还需要使用反射调用 Func 构造函数。这也很复杂,因为它IMessage也是通用的。

您还需要重新定义ExecuteMessage为泛型以匹配委托类型:

static object ExecuteMessage<T>(IMessage<T> message)
{
    return null;
}

我认为您需要的代码如下:

var executeMethod = typeof(Program).GetMethod(nameof(ExecuteMessage), BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var type in serviceTypes)
{
    var messageType = typeof(IMessage<>).MakeGenericType(type);
    var funcType = typeof(Func<,>).MakeGenericType(messageType, typeof(object));
    var func = executeMethod.MakeGenericMethod(type).CreateDelegate(funcType, this);  // don't pass this for static methods
    registerHandlerMethod.MakeGenericMethod(type).Invoke(server, new object[] { func });
}

推荐阅读