我有一个应用程序,它由几个不同的程序集组成,其中一个程序集包含类所遵循的各种接口,以及类通过程序集边界进行通信。有几个类触发事件,有几个对这些事件感兴趣。
我的问题如下:实现某种中央EventConsolidator是一种好习惯吗?这将是高度耦合的,因为它需要知道抛出事件的每个类(或至少是接口),并且事件的每个消费者都需要具有对EventConsolidator的引用才能订阅。
目前我的情况是A级知道B级(但不是C级),B级知道C级等等。然后如果C触发事件B需要将其取出并触发自己的事件以便A到响应。这些类型的链可能会变得很长,并且B可能只对事件感兴趣才能传递它。我不希望A知道C,因为这会破坏封装。
在这种情况下,有什么好的做法?集中事件,或者咧嘴笑,并在每个中间阶段定义事件?或者做出决定的标准是什么?谢谢!
编辑:Here是另一个问题基本相同的问题。
答案 0 :(得分:8)
您可以将事件本身放在一个界面中,这样A不需要直接了解C,而只需知道它有相关事件。但是,也许你的意思是A的实例没有看到C的实例...
我会试着避开集中的事件系统。它可能会使测试变得更加困难,并且如你所说的那样引入紧耦合。
值得了解的一个模式是使事件代理变得简单。如果B仅公开事件以将其代理为C,则可以执行以下操作:
public event FooHandler Foo
{
add
{
c.Foo += value;
}
remove
{
c.Foo -= value;
}
}
这样它代理订阅/取消订阅而不是提升事件的行为。当然,这对GC的资格有影响 - 根据具体情况,这可能有益或无益。值得思考。
答案 1 :(得分:6)
您可以尝试使用NInject或Unity Application Block的事件代理。
这允许你,例如:
[Publish("foo://happened")]
public event EventHandler<FooArgs> FooHappened;
[Subscribe("foo://happened")]
public void Foo_Happened(object sender, FooArgs args)
{ }
如果通过容器创建了两个对象,则事件将自动连接。
答案 2 :(得分:1)
我可能会尝试按下域,以便每个类可以直接依赖于相应的事件源。我的意思是问为什么A不知道C?是否有D等待出现?
作为替代方法,您可以考虑使用事件代理体系结构。这意味着观察者不直接了解来源。这是一个有趣的video。
答案 3 :(得分:1)
这将是高度耦合的,因为它需要知道每个类
如果您认为耦合不好,我想你回答了自己的问题!在许多环境中,通过一系列潜在处理程序传递事件是一种相当常见的模式;它可能不是最有效的方法,但它避免了您建议的方法所涉及的复杂性。
您可以采用的另一种方法是使用消息调度程序。这涉及使用公共消息格式(或至少是公共消息头格式)来表示事件,然后将这些消息放入队列中。然后,调度程序依次(或基于某些优先级)获取每个事件,并将它们直接路由到所需的处理程序。每个处理程序必须在启动时向调度程序注册。
在这种情况下,消息可能只是一个开头有几个特定字段的类。特定邮件可能只是衍生邮件,或者您可以将邮件特定数据作为“对象”参数与邮件标头一起传递。
答案 4 :(得分:1)
如果您想要集中活动,可以在M $模式和实践库中查看EventBroker对象。
就我个人而言,我认为更好地考虑一下你的体系结构,即使我们在这里使用EventBroker,我们的新代码都没有使用它,我们希望在阳光灿烂的日子里逐步淘汰它。
答案 5 :(得分:0)
我们有自己的事件代理实现(开源) 教程:http://sourceforge.net/apps/mediawiki/bbvcommon/index.php?title=Event_Broker
性能分析:www.planetgeek.ch/2009/07/12/event-broker-performance /
与CAB相比的优势: - 更好的伐木 - 扩展支持 - 更好的错误处理 - 可扩展处理程序(UI,后台线程,...) 还有一些我现在不记得了。
干杯, URS