类似SCSF中EventBroker解耦事件调用方和接受方,打破"+="带来的耦合

来源:互联网 发布:js如何获取对象的长度 编辑:程序博客网 时间:2024/06/05 04:41

今天在网上闲逛,偶然发现一个老外的开源组件,里面实现了微软SCSF框架中的EventBroker模块的功能,它的使用和SCSF几乎一样,熟悉SCSF的人几乎一下就能上手,只是这个类库不再像SCSF一样,只能在框架中使用,它不依赖于SCSF,可以用在WinForm,WPF中,是一个独立的组件


原本应该在"Code Project"上可以下载的,上面只有它的介绍,下载链接好像有问题

http://www.codeproject.com/Articles/30066/EventBroker-a-notification-component-for-synchrono


我在百度上找了很久,终于找到一个可以下载的地方,这里是它的源码。

http://sourceforge.net/projects/bbvcommon/


我之所以青睐这个库,是因为它用C#的Attribute解耦了事件注册时由"+="带来的调用方与接收方的依赖(当然解耦的方式有很多,但我觉得这个方式最优雅)

下面就是一个事件发布类,它采用了Attribute来标记,其中的"topic://EventBrokerSample/SimpleEvent"为事件的Uri,是他的唯一标示。

public class Publisher{    [EventPublication("topic://EventBrokerSample/SimpleEvent")]    public event EventHandler SimpleEvent;        ///<summary>Fires the SimpleEvent</summary>    public void CallSimpleEvent()    {        SimpleEvent(this, EventArgs.Empty);    }}
下面是事件的订阅部分,同样是用Attribute来标记,采用同样的Uri来标示为上面事件的接收

public class Subscriber{    [EventSubscription(        "topic://EventBrokerSample/SimpleEvent",         typeof(Handlers.Publisher))]    public void SimpleEvent(object sender, EventArgs e)    {        // do something useful or at least funny    }}
最后,包含事件订阅的对象需要EventBroker来注册,这个相当与"+=",只是它可以完全不关注事件的发布者是谁(这和SCSF的方式一模一样),它使用的是反射Attribute元数据的方式,然后调用DynamicInvoke方法调用委托

下面是我使用该组件的一个例子


窗体上下,各自放了一个UserControl,首先他们加载的时候,接受了窗体Form1触发的事件,然后点击UserControl1的按钮改变UserControl2的文本框文本,反之UserControl2亦然,我用单例模式把EventBroker对象管理了起来,不然使用起来太不方便了

[csharp] view plain copy print?
  1. public class EventBrokerCreator  
  2. {  
  3.     private static EventBroker _instance = null;  
  4.     private EventBrokerCreator()  
  5.     {}  
  6.   
  7.     public static EventBroker GetEventBroker()  
  8.     {  
  9.         return _instance ?? (_instance = new EventBroker());  
  10.     }  
  11. }  
下面是两个用户控件,他们各自定义了事件的发布和订阅
[csharp] view plain copy print?
  1. public partial class UserControl1 : UserControl  
  2. {  
  3.     public UserControl1()  
  4.     {  
  5.         InitializeComponent();  
  6.     }  
  7.   
  8.     [EventPublication(EventTopics.UserCtrol1)]  
  9.     public event EventHandler UserCtrol1Event;  
  10.   
  11.     private void button1_Click(object sender, EventArgs e)  
  12.     {  
  13.         if (UserCtrol1Event != null)  
  14.             UserCtrol1Event(this, EventArgs.Empty);  
  15.     }  
  16.   
  17.     [EventSubscription(EventTopics.UserCtrol2, typeof(Publisher))]  
  18.     public void UserCtrol1Send(object sender, EventArgs e)  
  19.     {  
  20.         textBox1.Text = "UserControl2 Send";  
  21.     }  
  22.   
  23.     [EventSubscription(EventTopics.Form1, typeof(Publisher))]  
  24.     public void Form11Send(object sender, EventArgs e)  
  25.     {  
  26.         textBox1.Text = "Form1 Send";  
  27.     }  
  28. }  

[csharp] view plain copy print?
  1. public partial class UserControl2 : UserControl  
  2. {  
  3.     public UserControl2()  
  4.     {  
  5.         InitializeComponent();  
  6.     }  
  7.   
  8.     [EventPublication(EventTopics.UserCtrol2)]  
  9.     public event EventHandler UserCtrol2Event;  
  10.   
  11.     private void button1_Click(object sender, EventArgs e)  
  12.     {  
  13.         if (UserCtrol2Event != null)  
  14.             UserCtrol2Event(this, EventArgs.Empty);  
  15.     }  
  16.   
  17.     [EventSubscription(EventTopics.UserCtrol1, typeof(Publisher))]  
  18.     public void UserCtrol1Send(object sender, EventArgs e)  
  19.     {  
  20.         textBox1.Text = "UserControl1 Send";  
  21.     }  
  22.   
  23.     [EventSubscription(EventTopics.Form1, typeof(Publisher))]  
  24.     public void Form11Send(object sender, EventArgs e)  
  25.     {  
  26.         textBox1.Text = "Form1 Send";  
  27.     }  
  28. }  

在Form1中发布一个事件,两个用户控件来订阅
[csharp] view plain copy print?
  1. public partial class Form1 : Form  
  2. {  
  3.     public Form1()  
  4.     {  
  5.         //为了方便说明,用户控件的实例化部分从Designer.cs中移到这里  
  6.         this.userControl1 = new Sample.UserControl1();  
  7.         this.userControl2 = new Sample.UserControl2();  
  8.         //注册事件订阅对象  
  9.         var eventBroker = EventBrokerCreator.GetEventBroker();  
  10.         eventBroker.Register(userControl1);  
  11.         eventBroker.Register(userControl2);  
  12.         InitializeComponent();  
  13.     }  
  14.   
  15.     [EventPublication(EventTopics.Form1)]  
  16.     public event EventHandler Form1Event;  
  17.   
  18.     private void Form1_Load(object sender, EventArgs e)  
  19.     {  
  20.         if (Form1Event != null)  
  21.             Form1Event(this, EventArgs.Empty);  
  22.     }  
  23. }  
最后还需要在Program.cs中对Form1进行EventBroker的注册
[csharp] view plain copy print?
  1. static void Main()  
  2. {  
  3.     Application.EnableVisualStyles();  
  4.     Application.SetCompatibleTextRenderingDefault(false);  
  5.   
  6.     //由于是单例模式,所有的EventBroker对象都是同一个  
  7.     var eventBroker = EventBrokerCreator.GetEventBroker();  
  8.     var form1 = new Form1();  
  9.     eventBroker.Register(form1);  
  10.   
  11.     Application.Run(form1);  
  12. }  
好了,大功告成了,有兴趣的人可以自己写个demo玩一下,个人觉得 eventBroker.Register(form1);这种注册的方式不够优雅,还有改进的余地。
原创粉丝点击