c# - 使用静态类/事件作为应用程序消息总线是否存在缺陷

标签 c# generics events

我有一个静态泛型类,它可以帮助我以很少的开销移动事件:

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)”。

我有几个问题:

  1. fxCop 提示将静态方法与泛型一起使用,但这正是我在这里所追求的。我希望每种处理的消息类型都有一个 MessageBus。将 static 与泛型结合使用使我无需编写维护 MessageBus 对象列表的所有代码。

  2. 监听对象是否通过 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/

相关文章:

c# - 在泛型集合中使用 LINQ

c# - 事件订阅者是否按订阅顺序调用?

kotlin - 为什么我的通用 Kotlin 函数中的此转换未被选中?

java - 为什么我的 Android 陀螺仪应用程序不会触发任何事件?

c# - 使用动态确定的类类型静态定义成员

c# - 在新子集合中枚举时集合被修改异常

c# - 在 System.Data.SqlCommand (C#) 中使用子查询 - 语法错误,在 SQL Server Mgmt Studio 中工作

Java 泛型集合和继承

java - 从 .class (Class<?>) 调用 Object 的 toString() 方法

javascript - Chaplin/Backbone 问题 - 将项目添加到集合时未触发 "Add"事件