multiple - Un simple bus de eventos para.NET
generics c# (8)
El bloque de aplicaciones compuestas incluye un agente de eventos que podría serle útil.
Quiero hacer un bus de eventos muy simple que permita a cualquier cliente suscribirse a un tipo particular de evento y cuando cualquier editor empuje un evento en el bus utilizando el método EventBus.PushEvent()
solo los clientes que se suscribieron a ese tipo de evento en particular lo harán obtener el evento.
Estoy usando C # y .NET 2.0.
Debes ver el episodio 3 en Hibernating Rhinos , la serie de proyecciones de Ayende - "Implementing the event broker".
Muestra cómo se puede implementar un corredor de eventos muy simple usando Windsor para cablear las cosas. El código fuente está incluido también.
La solución de corredor de eventos propuesta es muy simple, pero no tomaría demasiadas horas aumentar la solución para permitir que los argumentos se pasen junto con los eventos.
También puede consultar las extensiones de 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();
}
¿Hay mejores?
Otra buena implementación se puede encontrar en:
http://code.google.com/p/fracture/source/browse/trunk/Squared/Util/EventBus.cs
Los casos de uso están disponibles en: /trunk/Squared/Util/UtilTests/Tests/EventTests.cs
Esta implementación no necesita una biblioteca externa.
Una mejora puede ser poder suscribirse con un tipo y no una cadena.
Encontré Generic Message Bus . Es una clase simple.
Creé esto:
https://github.com/RemiBou/RemiDDD/tree/master/RemiDDD.Framework/Cqrs
Hay una dependencia con ninject. Tienes un MessageProcessor. Si desea obserar un evento, implemente "IObserver" si desea manejar un comando implementar "ICommandHandleer"
Otro, inspirado en EventBus para Android, pero mucho más simple:
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 });
}
}
}
Caso de uso:
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));
// ...
}
}
Tiny Messenger es una buena opción, lo he estado utilizando en un proyecto en vivo durante 2,5 años. Algunos ejemplos de código de Wiki (enlace a continuación):
Publicación
messageHub.Publish(new MyMessage());
Suscribirse
messageHub.Subscribe<MyMessage>((m) => { MessageBox.Show("Message Received!"); });
messageHub.Subscribe<MyMessageAgain>((m) => { MessageBox.Show("Message Received!"); }, (m) => m.Content == "Testing");
El código está en GitHub: https://github.com/grumpydev/TinyMessenger
El Wiki parece estar aún en BitBucket: https://bitbucket.org/grumpydev/tinyioc/wiki/TinyMessenger
También tiene un paquete de Nuget
Install-Package TinyMessenger