.NET 的简单事件总线 [关闭]
Posted
技术标签:
【中文标题】.NET 的简单事件总线 [关闭]【英文标题】:A simple event bus for .NET [closed] 【发布时间】:2008-12-15 12:49:17 【问题描述】:我想制作一个非常简单的事件总线,它允许任何客户端订阅特定类型的事件,并且当任何发布者使用 EventBus.PushEvent()
方法在总线上推送事件时,只有订阅该特定事件类型的客户端将得到该事件。
我正在使用 C# 和 .NET 2.0。
【问题讨论】:
基于redis的消息队列github.com/antirez/disque 【参考方案1】: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");
代码在 GitHub 上:https://github.com/grumpydev/TinyMessenger
维基在这里:https://github.com/grumpydev/TinyMessenger/wiki
它还有一个 Nuget 包
Install-Package TinyMessenger
【讨论】:
+1 为 TinyMessenger,微型消息总线。【参考方案2】:另一个,受 EventBus for android 的启发,但更简单:
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 );
用例:
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));
// ...
【讨论】:
【参考方案3】:Composite Application Block 包含一个可能对您有用的事件代理。
【讨论】:
【参考方案4】:您还可以查看 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();
还有更好的吗?
【讨论】:
【参考方案5】:我找到了Generic Message Bus 。这是一个简单的类。
【讨论】:
【参考方案6】:另一个很好的实现可以在:
http://code.google.com/p/fracture/source/browse/trunk/Squared/Util/EventBus.cs
用例可在以下位置访问: /trunk/Squared/Util/UtilTests/Tests/EventTests.cs
此实现不需要外部库。
一个改进可能是能够订阅类型而不是字符串。
【讨论】:
【参考方案7】:您应该查看Hibernating Rhinos 中的第 3 集,Ayende 的屏幕投射系列 - “实现事件代理”。
它展示了如何使用 Windsor 实现一个非常简单的事件代理来连接事物。源代码也包含在内。
提议的事件代理解决方案非常简单,但不需要太多时间来扩充解决方案以允许参数与事件一起传递。
【讨论】:
【参考方案8】:我创造了这个:
https://github.com/RemiBou/RemiDDD/tree/master/RemiDDD.Framework/Cqrs
ninject 存在依赖关系。 你有一个消息处理器。如果你想观察一个事件,实现“IObserver”如果你想处理一个命令实现“ICommandHandleer”
【讨论】:
以上是关于.NET 的简单事件总线 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
MassTransit一个优秀的.NET消息(事件)总线框架