Dealing with memory leak is not as far as some might think it is. But it doesn’t get serious until it is very late to change the fundamentals of our software design.
hear.BeatEvent += right.BeatHandler
The idea is to change this aby using an event manager, in my sample I have called it Brain, to handle de notifications like
Brain.AddListener(heart, right);
And to unsubscribe to the event you do something like
Brain.RemoveListener(heart, right);
To make this possible, you need to make sure that your Hand class where the events need to be handled, you implement the IWeakEventListener interface which brings us to ReceiveWeakEvent method:
/// <summary> Receives events from the centralized event manager. </summary>
/// <returns> true if the listener handled the event. </returns>
/// <param name="managerType">The type of the <see cref="T:System.Windows.WeakEventManager"/> calling this method.</param>
/// <param name="sender">Object that originated the event.</param>
/// <param name="e">Event data.</param>
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if (managerType == typeof(Brain))
{
var beat = e as BeatArgs;
Trace.WriteLine(string.Format("{0} hand is getting the beat from {1}", name, beat.TimeOfBeat.ToString("hh:mm:ss")));
return true;
}
return false;
}
The Brain class which has a Singleton implementation provides only two public methods i.e. AddListener
and RemoveListener
. They do this by calling the protected methods and passing the parameters:
/// <summary>Subscribe a body part to listen to heart beat </summary>
/// <param name="source">the heart to listen to</param>
/// <param name="listener">the body that subscribes</param>
public static void AddListener(Heart source, IWeakEventListener listener)
{
Neuron.ProtectedAddListener(source, listener);
}
/// <summary>Unsubscribe a body part to listen to heart beat </summary>
/// <param name="source">the heart to listen to</param>
/// <param name="listener">the body that subscribes</param>
public static void RemoveListener(Heart source, IWeakEventListener listener)
{
Neuron.ProtectedRemoveListener(source, listener);
}
That is not all what brain do internally. It is actually inheriting the abstract class WeakEventManager
and in order to do that it overrides the StartListening
and StopListening
methods that are internally called when it should be.
/// <summary>Starts listening on the provided heart for the managed beat event.</summary>
/// <param name="source">The heart to disconnect beat event</param>
protected override void StartListening(object source)
{
var heart = source as Heart;
if (heart == null) throw new ArgumentException("The brain suppose to listen to heart only");
heart.BeatEventHandler += DeliverEvent;
}
/// <summary>Stops listening on the provided heart for the managed beat event.</summary>
/// <param name="source">The heart to disconnect beat event</param>
protected override void StopListening(object source)
{
var heart = source as Heart;
if (heart == null) throw new ArgumentException("The brain suppose to listen to heart only");
heart.BeatEventHandler -= DeliverEvent;
}
The last part is the Heart where the event is getting fired. That is nothing special and can be implemented as before.
/// <summary> Can beat and can e subscribed to the beat event handler </summary>
public partial class Heart
{
/// <summary>Hanldler for notifying a beat </summary>
public event EventHandler<BeatArgs> BeatEventHandler;
/// <summary>Sends the beat through the events </summary>
/// <param name="beatArgs"></param>
protected void OnSendBeat(BeatArgs beatArgs)
{
if (BeatEventHandler != null)
BeatEventHandler(this, beatArgs);
}
/// <summary>Create a beat and send it </summary>
private void BeatOnce()
{
OnSendBeat(new BeatArgs());
}
}