问题
I want to make a very simple event bus which will allow any client to subscribe to a particular type of event and when any publisher pushes an event on the bus using EventBus.PushEvent()
method only the clients that subscribed to that particular event type will get the event.
I am using C# and .NET 2.0.
回答1:
Tiny Messenger is a good choice, I've been using it in a live project for 2.5 years now. Some code examples from the Wiki (link below):
Publishing
messageHub.Publish(new MyMessage());
Subscribing
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
回答2:
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));
// ...
}
}
回答3:
You might also check out Unity extensions: 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();
}
Are there better ones?
回答4:
I found Generic Message Bus . It is one simple class.
回答5:
The Composite Application Block includes an event broker that might be of use to you.
回答6:
Another good implementation can be found at:
http://code.google.com/p/fracture/source/browse/trunk/Squared/Util/EventBus.cs
Use cases is accessible at: /trunk/Squared/Util/UtilTests/Tests/EventTests.cs
This implementation does not need external library.
An improvement may be to be able to subscribe with a type and not a string.
回答7:
You should check out episode 3 in Hibernating Rhinos, Ayende's screen casts series - "Implementing the event broker".
It shows how you can implement a very simple event broker using Windsor to wire things up. Source code is included as well.
The proposed event broker solution is very simple, but it would not take too many hours to augment the solution to allow arguments to be passed along with the events.
回答8:
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"
来源:https://stackoverflow.com/questions/368265/a-simple-event-bus-for-net