gpt4 book ai didi

c# - 通用消息处理程序

转载 作者:太空狗 更新时间:2023-10-29 19:40:59 24 4
gpt4 key购买 nike

我想在 C# 中创建一个处理消息的通用机制。我的小应用程序需要这个,所以我不想使用完整的消息总线。我的要求很简单:

  • 我想为消息设置几个类,即 Message1 , Message2 .他们可以从一个基类继承,这不是问题,但如果他们不这样做我也不在乎。目前他们确实继承自 Message .
  • 能够获得每个消息类别的处理程序。即如果我发送 Message1 , 然后 Message1Handler类应该被实例化。处理程序必须执行 IMessageHandler<T>其中 T是消息类。 IMessageHandler定义如下:

    interface IMessageHandler<T>
    {
    void Execute(T message);
    }

我写了一个简单的“Resolver”类:

public static class HandlerRegistry
{
private static readonly Dictionary<string, Type> _handlers = new Dictionary<string, Type>();


public static void Register<T, T2>() where T2: IMessageHandler<T>
{
_handlers.Add(typeof(T).FullName, typeof(T2));

}

public static IMessageHandler<T> Resolve<T>(T parameters)
{
var type = _handlers[parameters.GetType().FullName];
return (IMessageHandler<T>) Activator.CreateInstance(type);
}
}

在此实现中,一切正常,但有一部分 - 强制转换为 IMessageHandler。当我试图将它与消息集合一起使用时,会发生这种情况:编译器在编译时不知道集合中将包含哪些实际消息——它只是假设它们都是 Message 的子类。 , 所以它试图投 IMessageHandler<ConcreteMessage>IMessageHandler<Message>显然我遇到了无效转换的异常。在这种情况下,逆变可能会有所帮助,但我无法将参数声明为 out,因为我在 Execute 方法参数中有消息。

有人知道这个问题的优雅解决方案吗?我知道我可以让它“更多的运行时间” - 而不是使用泛型只是声明 void Execute(Message m)在每个处理程序中,首先尝试转换为我期望的类型,但正如有人在某处所说的那样——您编写的每个转换都破坏了使用类型系统的全部意义。

最佳答案

选项 1

如果你不关心使用反射。您可以添加 Execute HandlerRegistry 的方法而不是将处理程序返回给调用者:

public static void Execute<T>(T parameters)
{
var type = _handlers[parameters.GetType().FullName];
var handler = Activator.CreateInstance(type);
type.GetMethod("Execute", new[] { parameters.GetType() })
.Invoke(handler, new object[] { parameters });
}

选项 2

如果您不关心一个消息处理程序只能订阅一条消息。我们可以利用 Explicit Interface Implementation C#的特点:

// NOTE: This interface is not generic
public interface IMessageHandler
{
void Execute(object message);
}

public abstract class MessageHandler<T> : IMessageHandler
{
public abstract void Execute(T message);

// NOTE: Here we explicitly implement the IMessageHandler
void IMessageHandler.Execute(object message)
{
Execute((T)message);
}
}

现在您的 resolve 方法可以更改为:

public static IMessageHandler Resolve<T>(T parameters)
{
var type = _handlers[parameters.GetType().FullName];
return (IMessageHandler)Activator.CreateInstance(type);
}

顺便说一句,我个人更愿意传入 Type而不是消息实例。

然后让你的处理程序继承通用抽象 MessageHandler<T>而不是实现 IMessageHandler :

public class HandlerA : MessageHandler<MessageA>
{
public override void Execute(MessageA message)
{
Console.WriteLine("Message A");
}
}

public class HandlerB : MessageHandler<MessageB>
{
public override void Execute(MessageB message)
{
Console.WriteLine("Message B");
}
}

关于c# - 通用消息处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28531158/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com