我想制作一个非常简单的事件总线,它允许任何客户端订阅特定类型的事件,并且当任何发布者使用EventBus.PushEvent()
方法在总线上推送事件时,只有订阅该特定事件类型的客户端才会获得该事件。
我正在使用 C# 和 .NET 2.0。
Tiny Messenger 是一个不错的选择,我已经在现场项目中使用它 2.5 年了。来自 Wiki 的一些代码示例(下面的链接):
出版
messageHub.Publish(new MyMessage());
订阅
messageHub.Subscribe<MyMessage>((m) => { MessageBox.Show("Message Received!"); });
messageHub.Subscribe<MyMessageAgain>((m) => { MessageBox.Show("Message Received!"); }, (m) => m.Content == "Testing");
The code's on GitHub: https://github.com/grumpydev/TinyMessenger
The Wiki is here: https://github.com/grumpydev/TinyMessenger/wiki
It has a Nuget package also
Install-Package TinyMessenger
Another one, inspired by EventBus for android, but far simpler:
public class EventBus
{
public static EventBus Instance { get { return instance ?? (instance = new EventBus()); } }
public void Register(object listener)
{
if (!listeners.Any(l => l.Listener == listener))
listeners.Add(new EventListenerWrapper(listener));
}
public void Unregister(object listener)
{
listeners.RemoveAll(l => l.Listener == listener);
}
public void PostEvent(object e)
{
listeners.Where(l => l.EventType == e.GetType()).ToList().ForEach(l => l.PostEvent(e));
}
private static EventBus instance;
private EventBus() { }
private List<EventListenerWrapper> listeners = new List<EventListenerWrapper>();
private class EventListenerWrapper
{
public object Listener { get; private set; }
public Type EventType { get; private set; }
private MethodBase method;
public EventListenerWrapper(object listener)
{
Listener = listener;
Type type = listener.GetType();
method = type.GetMethod("OnEvent");
if (method == null)
throw new ArgumentException("Class " + type.Name + " does not containt method OnEvent");
ParameterInfo[] parameters = method.GetParameters();
if (parameters.Length != 1)
throw new ArgumentException("Method OnEvent of class " + type.Name + " have invalid number of parameters (should be one)");
EventType = parameters[0].ParameterType;
}
public void PostEvent(object e)
{
method.Invoke(Listener, new[] { e });
}
}
}
Use case:
public class OnProgressChangedEvent
{
public int Progress { get; private set; }
public OnProgressChangedEvent(int progress)
{
Progress = progress;
}
}
public class SomeForm : Form
{
// ...
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EventBus.Instance.Register(this);
}
public void OnEvent(OnProgressChangedEvent e)
{
progressBar.Value = e.Progress;
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
EventBus.Instance.Unregister(this);
}
}
public class SomeWorkerSomewhere
{
void OnDoWork()
{
// ...
EventBus.Instance.PostEvent(new OnProgressChangedEvent(progress));
// ...
}
}
复合应用程序块包括一个可能对您有用的事件代理。
我找到了通用消息总线。这是一门简单的课。
您还可以查看 Unity 扩展:http: //msdn.microsoft.com/en-us/library/cc440958.aspx
[Publishes("TimerTick")]
public event EventHandler Expired;
private void OnTick(Object sender, EventArgs e)
{
timer.Stop();
OnExpired(this);
}
[SubscribesTo("TimerTick")]
public void OnTimerExpired(Object sender, EventArgs e)
{
EventHandler handlers = ChangeLight;
if(handlers != null)
{
handlers(this, EventArgs.Empty);
}
currentLight = ( currentLight + 1 ) % 3;
timer.Duration = lightTimes[currentLight];
timer.Start();
}
有更好的吗?
另一个很好的实现可以在以下位置找到:
http://code.google.com/p/fracture/source/browse/trunk/Squared/Util/EventBus.cs
用例可在以下位置访问:/trunk/Squared/Util/UtilTests/Tests/EventTests.cs
此实现不需要外部库。
改进可能是能够订阅类型而不是字符串。
您应该查看Hibernating Rhinos中的第 3 集,Ayende 的屏幕演员系列 - “实现事件代理”。
它展示了如何使用 Windsor 来实现一个非常简单的事件代理。源代码也包括在内。
提议的事件代理解决方案非常简单,但不需要太多时间来扩充解决方案以允许参数与事件一起传递。
I created this :
https://github.com/RemiBou/RemiDDD/tree/master/RemiDDD.Framework/Cqrs
There is a dependancy with ninject. You got a MessageProcessor. If you want to obsere an event, implement "IObserver" if you want to handle a command implement "ICommandHandleer"