Click here to Skip to main content
15,886,798 members
Articles / Desktop Programming / Windows Forms

An Easy to Use Weak Referenced Event Handler Factory for .NET 2.0

Rate me:
Please Sign up or sign in to vote.
4.84/5 (19 votes)
9 Mar 200710 min read 152K   932   87  
An article on creating weak event handlers that show how to use them in a Windows Form.
// ****************************************************************************
// Copyright Swordfish Computing Australia 2005                              **
// http://www.swordfish.com.au/                                              **
//                                                                           **
// Filename: Swordfish\Collections\WeakReferenceToEventHandler.cs            **
// Authored by: John Stewien of Swordfish Computing                          **
// Date: September 2005                                                      **
//                                                                           **
// - Change Log -                                                            **
// ****************************************************************************
// $Id: WeakReferenceToEventHandler.cs,v 1.5 2005/10/05 08:37:52 stewienj Exp $

using System;
using System.Reflection;

namespace Swordfish.Collections
{
	/// <summary>
	/// Holds a weak reference to an event handler
	/// </summary>
	public class WeakReferenceToEventHandler<TEventArgs> : WeakReference where TEventArgs : EventArgs
	{
		// ********************************************************************
		// Private Fields
		// ********************************************************************
		#region Private Fields

		/// <summary>
		/// Store the event source so that the event handler can be removed
		/// automatically when the original event handler gets garbage
		/// collected. Just keep a weak reference so as not to hold the
		/// event source object alive
		/// </summary>
		private WeakReference weakReferenceToEventSource;
		/// <summary>
		/// The name of the event in the event source. Stored so that the event
		/// handler can be removed.
		/// </summary>
		private string eventName;

		#endregion Private Fields

		// ********************************************************************
		// Public Methods
		// ********************************************************************
		#region Public Methods

		/// <summary>
		/// Constructor. Initialises class fields from an event handler
		/// </summary>
		/// <param name="eventHandler"></param>
		public WeakReferenceToEventHandler(EventHandler<TEventArgs> eventHandler) : base(eventHandler)
		{
		}

		/// <summary>
		/// This is an intermediate event handler that the event source
		/// has a strong reference to.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		public void IntermediateEventHandler(object sender, TEventArgs e)
		{
			EventHandler<TEventArgs> original = this.EventHandler;
			if (original != null)
			{
				original(sender, e);
			}
			else
			{
				RemoveHandler();

				// if the original event handler is null, then the
				// WeakEventHandlerFactory list no longer exists as
				// the list holds a strong reference to the original
				// event handler. Thus there is no need to worry
				// about removing this handler from the list in the
				// WeakEventHandlerFactory object.
			}
		}

		/// <summary>
		/// Adds the weak referenced event handler to the event passed in. Note
		/// that an event can't be passed to a method, so the name of the
		/// event is passed instead.
		/// </summary>
		/// <param name="eventSource"></param>
		/// <param name="eventName"></param>
		public void AddHandler(object eventSource, string eventName)
		{
			// Store the event source detail
			this.eventName = eventName;
			weakReferenceToEventSource = new WeakReference(eventSource);

			// Create and intermediate handler that the event source will
			// have a strong reference to
			EventInfo eventInfo = eventSource.GetType().GetEvent(eventName);
			eventInfo.AddEventHandler(eventSource, new EventHandler<TEventArgs>(IntermediateEventHandler));
		}

		/// <summary>
		/// Removes the intermediate event handler from the event source object
		/// </summary>
		public void RemoveHandler()
		{
			if (weakReferenceToEventSource == null)
				return;

			object eventSource = weakReferenceToEventSource.Target;
			if (eventSource != null)
			{
				// Get the event using reflection
				EventInfo eventInfo = eventSource.GetType().GetEvent(eventName);

				// Remove the intermediate event handler, which will dereference
				// this weak reference and allow it to be garbage collected.
				eventInfo.RemoveEventHandler(eventSource, new EventHandler<TEventArgs>(IntermediateEventHandler));
			}
		}

		#endregion Public Methods

		// ********************************************************************
		// Properties
		// ********************************************************************
		#region Properties

		/// <summary>
		/// Gets the original event handler
		/// </summary>
		public EventHandler<TEventArgs> EventHandler
		{
			get
			{
				return this.Target as EventHandler<TEventArgs>;
			}
		}

		/// <summary>
		/// Gets the source of the event
		/// </summary>
		public object EventSource
		{
			get
			{
				if (weakReferenceToEventSource != null)
					return weakReferenceToEventSource.Target;
				else
					return null;
			}
		}

		/// <summary>
		/// Gets the event name
		/// </summary>
		public string EventName
		{
			get
			{
				return eventName;
			}
		}

		#endregion Properties
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Founder Cheesy Design
Taiwan Taiwan
John graduated from the University of South Australia in 1997 with a Bachelor of Electronic Engineering Degree, and since then he has worked on hardware and software in many fields including Aerospace, Defence, and Medical giving him over 10 of years experience in C++ and C# programming. In 2009 John Started his own contracting company doing business between Taiwan and Australia.

Comments and Discussions