Here is the simple implementation of EventBroker service. You can use in your aplications to implement communicationamong loosely connected components like plugins for example. EventBroker follows publisher / subscriber pattern.
I am preparing pacakaged building block with associated tests and sample application. It will be published in next few days.
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace HiveStudios.UI.Framework.Events
{
public delegate void GlobalEventHandler(object sender, GlobalEventEventArgs e);
public class GlobalEventEventArgs : EventArgs
{
private object data;
/// <summary>
/// Gets the data.
/// </summary>
/// <value>The data.</value>
public object Data
{
get { return data; }
set { data = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref="T:GlobalEventEventArgs"/> class.
/// </summary>
public GlobalEventEventArgs()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="T:GlobalEventEventArgs"/> class.
/// </summary>
/// <param name="myData">My data.</param>
public GlobalEventEventArgs(object myData)
: this()
{
data = myData;
}
}
internal class EventBroker
{
public static event EventHandler SubscriptionAdded;
public static event EventHandler SubscriptionRemoved;
private static volatile EventBroker instance;
private static object syncRoot = new Object();
private static Dictionary<string, List<Delegate>> subscriptions;
/// <summary>
/// Initializes a new instance of the <see cref="T:EventBroker"/> class.
/// </summary>
private EventBroker()
{
}
/// <summary>
/// Gets the instance.
/// </summary>
/// <value>The instance.</value>
public static EventBroker Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new EventBroker();
subscriptions = new Dictionary<string, List<Delegate>>();
}
}
}
return instance;
}
}
/// <summary>
/// Gets or sets the internal subscriptions dictionary.
/// </summary>
/// <value>The subscriptions.</value>
private static Dictionary<string, List<Delegate>> Subscriptions
{
get
{
return EventBroker.subscriptions;
}
set
{
lock (syncRoot)
{
EventBroker.subscriptions = value;
}
}
}
/// <summary>
/// Raises the subscription added event.
/// </summary>
/// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
private static void OnSubscriptionAdded(EventArgs e)
{
if (SubscriptionAdded != null)
SubscriptionAdded(instance, e);
}
/// <summary>
/// Raises the subscription removed event.
/// </summary>
/// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
private static void OnSubscriptionRemoved(EventArgs e)
{
if (SubscriptionRemoved != null)
SubscriptionRemoved(instance, e);
}
/// <summary>
/// Subscribe method to the specified event.
/// </summary>
/// <param name="id">The id.</param>
/// <param name="method">The method Delegate to be invoked when Event fires.</param>
public static void Subscribe(string id, Delegate method)
{
//Check if there is a existing event
List<Delegate> delegates = null;
if (Subscriptions == null)
Subscriptions = new Dictionary<string, List<Delegate>>();
if (Subscriptions.ContainsKey(id))
delegates = subscriptions[id];
else
{
delegates = new List<Delegate>();
Subscriptions.Add(id, delegates);
}
//add Delegate to List<Delegate>
delegates.Add(method);
OnSubscriptionAdded(new EventArgs());
}
/// <summary>
/// Unsubscribe method from event notifications
/// </summary>
/// <param name="id">The id.</param>
/// <param name="method">The method.</param>
public static void Unsubscribe(string id, Delegate method)
{
if (Subscriptions.ContainsKey(id)) //check if key exists
{
if (Subscriptions[id].Contains(method)) //check if delegate exists
{
Subscriptions[id].Remove(method); //remove delegate
OnSubscriptionRemoved(new EventArgs());
}
if (Subscriptions[id].Count == 0) //check id delegates.Count = 0
Subscriptions.Remove(id); //remove key
}
}
/// <summary>
/// Fire the specified event by id.
/// </summary>
/// <param name="id">The id.</param>
public static void Execute(string id)
{
if (Subscriptions.ContainsKey(id))
{
for (int i = 0; i < Subscriptions[id].Count; i++)
{
Delegate x = Subscriptions[id]
;
DynamicInvoke(id, x, null);
}
}
}
/// <summary>
/// Fire the specified event by and pass parameters.
/// </summary>
/// <param name="id">The id.</param>
/// <param name="args">The args.</param>
public static void Execute(string id, params object[] args)
{
if (Subscriptions.ContainsKey(id))
{
for (int i = 0; i < Subscriptions[id].Count; i++)
{
Delegate x = Subscriptions[id]
;
DynamicInvoke(id, x, args);
if (!Subscriptions.ContainsKey(id))
break;
}
}
}
/// <summary>
/// Checks to see if target of invocation is still al valid
/// (non-disposed objects). Then it dinamicly invokes Delegate.
/// </summary>
/// <param name="id">Event ID</param>
/// <param name="x">Delegate to invoke</param>
/// <param name="args">Object array of arguments</param>
private static void DynamicInvoke(string id, Delegate x, object[] args)
{
if (x.Method != null)
{
if (x.Target is Control)
{
Control ctl = (Control)x.Target;
if (ctl.IsDisposed)
{
Unsubscribe(id, x);
return;
}
}
if (x.Target == null)
{
Unsubscribe(id, x);
return;
}
x.DynamicInvoke(args);
}
}
}
}