C# 避免使用字典中的DynamicVoke()<;类型、委托>;

C# 避免使用字典中的DynamicVoke()<;类型、委托>;,c#,reflection,delegates,C#,Reflection,Delegates,我有一种MessageBroker类,它在运行时将传入的消息类型映射到处理程序方法。在处理程序中维护强类型消息对我来说很重要。它的工作原理是查找从IMessage继承的所有类,并创建一个Delegate,以调用任何具有Handles(TMessage)属性的方法,其中TMessage与传入的IMessage基础类型匹配 因此,“处理程序”如下所示: [Handles(typeof(TestMessage))] public void HandleTestMessage(objectsender,

我有一种MessageBroker类,它在运行时将传入的消息类型映射到处理程序方法。在处理程序中维护强类型消息对我来说很重要。它的工作原理是查找从
IMessage
继承的所有类,并创建一个
Delegate
,以调用任何具有
Handles(TMessage)
属性的方法,其中
TMessage
与传入的
IMessage
基础
类型
匹配

因此,“处理程序”如下所示:

[Handles(typeof(TestMessage))]
public void HandleTestMessage(objectsender, TestMessage request)
{
    var response = new TestResponse() { TestInt = request.TestInt };

    msgService.Send(sender, response);
}
同样,我真的希望避免在方法签名中使用
IMessage
,对我来说,不必在方法体中强制转换
IMessage
,这一点很重要

broker类使用以下方法来发现和注册处理程序:

/// <summary>
/// Subscribes all methods with the <see cref="HandlesAttribute"/> to the given <see cref="IMessage"/> <see cref="Type"/>
/// </summary>
/// <param name="target">The object to inspect</param>
public void SubscribeAll(object target)
{
    var targetType = target.GetType();

    // Get all private and public methods.
    var methods = targetType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
    foreach (var method in methods)
    {
        // If this method doesn't have the Handles attribute then ignore it.
        var handlesAttributes = (HandlesAttribute[])method.GetCustomAttributes(typeof(HandlesAttribute), false);
        if (handlesAttributes.Length != 1)
            continue;

        // The method must have only 2 arguments.
        var parameters = method.GetParameters();
        if (parameters.Length != 2)
        {
            log.LogDebug(string.Format("Method {0} has too many arguments", method.Name));
            continue;
        }

        // The second argument must be derived from IMessage.
        if (!typeof(IMessage).IsAssignableFrom(parameters[1].ParameterType))
        {
            log.LogDebug(string.Format("Method {0} does not have an IMessage as it's second argument", method.Name));
            continue;
        }

        Type genericDelegate; 

        if(method.ReturnType == typeof(void))
        {
            genericDelegate = typeof(Action<,>).MakeGenericType(parameters[0].ParameterType, handlesAttributes[0].MessageType);
        }
        else
        {
            genericDelegate = typeof(Func<,,>).MakeGenericType(parameters[0].ParameterType, handlesAttributes[0].MessageType, method.ReturnType);
        }

        var handler = method.CreateDelegate(genericDelegate, target);

        // Success, so register!
        Subscribe(
            handlesAttributes[0].MessageType,
            handler);
    }
}
当我将
MethodInfo
s转换为
Delegate
s(
Action
Func
)时,我认为我是聪明的,但我忽略了检查在
调用上使用
DynamicInvoke
的含义。事实证明,
DynamicInvoke
会产生相对较大的开销。因此,我的问题是,如何将处理程序
Delegate
s视为实际的
Delegate
s(同样,Action或Func)

如您所见,在
HandleMessage
中,我确实知道
消息的基本类型,并且发送者始终是一个对象。基本上,我需要做一些事情,比如:

((操作)处理程序)。调用(发送方、消息)

显然这是不可能的,但它清楚地说明了我正在努力实现的目标(我认为)

我尝试创建一种介于两者之间的通用方法:

public void InvokeHandler<TMessage>(Action<object, TMessage> handler, TMessage message, object sender = null)
public void InvokeHandler(操作处理程序,TMessage消息,object sender=null)

但我在尝试调用此方法时遇到了相反的问题。

此代码中的括号和/或尖括号不匹配(或者我的眼睛会:((Action@Flydog57是的,你是对的。我修复了它。你修复了上面的代码,还是解决了你的问题?如果你有MethodInfos,通过它们直接调用要比通过委托调用慢一些(如果我没记错的话,我10多年前就研究过这个问题),但速度仍然相当快;肯定比DynamicInvoke快。您可以通过反射创建一个动作对象,然后(通过反射)调用它,但是(猜测)它可能不会比DynamicInvoke快。我构建的工作类型半定期地使用MethodInfos做事情(尽管我已经停止检查它们的速度)。
public void InvokeHandler<TMessage>(Action<object, TMessage> handler, TMessage message, object sender = null)