我有一个静态泛型类,它可以帮助我以很少的开销移动事件:
public static class MessageBus<T> where T : EventArgs
{
public static event EventHandler<T> MessageReceived;
public static void SendMessage(object sender, T message)
{
if (MessageReceived != null)
MessageReceived(sender, message);
}
}
要创建系统范围的消息总线,我只需定义一个 EventArgs 类来传递任意位的信息:
class MyEventArgs : EventArgs
{
public string Message { get; set; }
}
任何我对这个事件感兴趣的地方,我只需连接一个处理程序:
MessageBus<MyEventArgs>.MessageReceived += (s,e) => DoSomething();
同样,触发事件也同样简单:
MessageBus<MyEventArgs>.SendMessage(this, new MyEventArgs() {Message="hi mom"});
使用 MessageBus 和自定义 EventArgs 类让我拥有一个用于特定类型消息的应用程序范围的消息接收器。当您有多个表单时,这会派上用场,例如,显示客户信息以及更新该信息的几个表单。没有一种形式相互了解,也不需要连接到静态“父类(super class)”。
我有几个问题:
fxCop 提示将静态方法与泛型一起使用,但这正是我在这里所追求的。我希望每种处理的消息类型都有一个 MessageBus。将 static 与泛型结合使用使我无需编写维护 MessageBus 对象列表的所有代码。
监听对象是否通过 MessageReceived 事件保持“事件”状态?
例如,也许我在 Form.Load 事件中有这段代码:
MessageBus<CustomerChangedEventArgs>.MessageReceived += (s,e) => DoReload();
当窗体关闭时,窗体是否保留在内存中,因为 MessageReceived 引用了它的 DoReload 方法?我是否应该在表单关闭时删除引用:
MessageBus<CustomerChangedEventArgs>.MessageReceived -= (s,e) => DoReload();
最佳答案
嗯,是的,你应该这样做,但如果你像你在示例中所做的那样使用 lambda 语法,我认为它不会起作用(我的意思是,处理程序将不会成功注销)。
如果我错了,请有人纠正我,但我相信这是真的,因为使用 lambda 语法有效地创建了一个新的 EventHandler<CustomerChangedEventArgs>
。对象,在内存中有自己的位置。当您尝试删除此处理程序时,再次使用 lambda 语法,这会创建 另一个 新的 EventHandler<CustomerChangedEventArgs>
对象,它不等于您创建的第一个对象;因此第一个永远不会被注销。
遗憾的是,我认为您实际上需要定义这样的方法:
DoReload(object sender, CustomerChangedEventArgs e) {
DoReload(); // your original overload, which doesn't actually care
// about the sender and e parameters
}
这样你就可以做到:
MessageBus<CustomerChangedEventArgs>.MessageReceived += DoReload;
之后:
MessageBus<CustomerChangedEventArgs>.MessageReceived -= DoReload;
关于c# - 使用静态类/事件作为应用程序消息总线是否存在缺陷,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2829703/