【发布时间】:2015-02-17 15:10:55
【问题描述】:
我想创建一个通用机制来处理 C# 中的消息。我在我的小应用程序中需要这个,所以我不想使用完整的消息总线。我的要求很简单:
- 我希望有几个消息类,即
Message1、Message2。他们可以从一个基类继承,这不是问题,但如果他们不这样做,我不在乎。目前他们确实继承自Message。 -
能够为每个消息类获取处理程序。即,如果我发送
Message1,那么应该实例化Message1Handler类。处理程序必须实现IMessageHandler<T>,其中T是消息类。IMessageHandler定义如下:interface IMessageHandler<T> { void Execute(T message); }
我写了一个简单的“解析器”类:
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) 并且在每个处理程序中,都从尝试转换为我期望的类型开始,但是正如有人在某处所说的那样-您编写的每一个转换都破坏了使用类型系统的全部意义。
【问题讨论】:
-
相关(只需阅读现在提到“命令”的“消息”):cuttingedge.it/blogs/steven/pivot/entry.php?id=91
-
这是相关的,但据我所知,他从未真正触及我的问题。他总是对从 IoC 注入的 ICommandHandler
接口进行操作。 -
这里不需要泛型......它没有添加任何东西......
-
我不会这样写,但它是一个很好的参考...stackoverflow.com/questions/1477471/…
-
顺便问一下,这是每个消息类型的单个处理程序,还是多个处理程序?