今天在网上闲逛,偶然发现一个老外的开源组件,里面实现了微软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对象管理了起来,不然使用起来太不方便了
public class EventBrokerCreator
{
private static EventBroker _instance = null;
private EventBrokerCreator()
{}
public static EventBroker GetEventBroker()
{
return _instance ?? (_instance = new EventBroker());
}
}
下面是两个用户控件,他们各自定义了事件的发布和订阅
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
[EventPublication(EventTopics.UserCtrol1)]
public event EventHandler UserCtrol1Event;
private void button1_Click(object sender, EventArgs e)
{
if (UserCtrol1Event != null)
UserCtrol1Event(this, EventArgs.Empty);
}
[EventSubscription(EventTopics.UserCtrol2, typeof(Publisher))]
public void UserCtrol1Send(object sender, EventArgs e)
{
textBox1.Text = "UserControl2 Send";
}
[EventSubscription(EventTopics.Form1, typeof(Publisher))]
public void Form11Send(object sender, EventArgs e)
{
textBox1.Text = "Form1 Send";
}
}
public partial class UserControl2 : UserControl
{
public UserControl2()
{
InitializeComponent();
}
[EventPublication(EventTopics.UserCtrol2)]
public event EventHandler UserCtrol2Event;
private void button1_Click(object sender, EventArgs e)
{
if (UserCtrol2Event != null)
UserCtrol2Event(this, EventArgs.Empty);
}
[EventSubscription(EventTopics.UserCtrol1, typeof(Publisher))]
public void UserCtrol1Send(object sender, EventArgs e)
{
textBox1.Text = "UserControl1 Send";
}
[EventSubscription(EventTopics.Form1, typeof(Publisher))]
public void Form11Send(object sender, EventArgs e)
{
textBox1.Text = "Form1 Send";
}
}
在Form1中发布一个事件,两个用户控件来订阅
public partial class Form1 : Form
{
public Form1()
{
//为了方便说明,用户控件的实例化部分从Designer.cs中移到这里
this.userControl1 = new Sample.UserControl1();
this.userControl2 = new Sample.UserControl2();
//注册事件订阅对象
var eventBroker = EventBrokerCreator.GetEventBroker();
eventBroker.Register(userControl1);
eventBroker.Register(userControl2);
InitializeComponent();
}
[EventPublication(EventTopics.Form1)]
public event EventHandler Form1Event;
private void Form1_Load(object sender, EventArgs e)
{
if (Form1Event != null)
Form1Event(this, EventArgs.Empty);
}
}
最后还需要在Program.cs中对Form1进行EventBroker的注册
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
//由于是单例模式,所有的EventBroker对象都是同一个
var eventBroker = EventBrokerCreator.GetEventBroker();
var form1 = new Form1();
eventBroker.Register(form1);
Application.Run(form1);
}
好了,大功告成了,有兴趣的人可以自己写个demo玩一下,个人觉得 eventBroker.Register(form1);这种注册的方式不够优雅,还有改进的余地。
我文中的源码这里可以下载