Click here to Skip to main content
15,892,809 members
Articles / Containers / Virtual Machine

Observable property pattern, memory leaks, and weak delegates for .NET

Rate me:
Please Sign up or sign in to vote.
4.96/5 (42 votes)
4 Dec 200624 min read 218.4K   359   174  
This article is dedicated to the observable property design pattern, a very nice pattern used in the Microsoft .NET Framework, a possible memory leak problem with it, and gives a couple of ways to solve it.
using System;
using System.Drawing;

using NUnit.Framework;

namespace Pvax.WeakDelegates.Tests
{
	/// <summary>
	/// A mock object that implements instance and static listeners for all 
	/// events from <see cref="EventSource/>."
	/// </summary>
	/// <remarks>
	/// For each {Event}Handler method there is a public boolean field 
	/// {Event}HandlerCalled. Set it fo <c>false</c>, raise the event and check
	/// if it has become <c>true</c>. If it is, then the event was successfully
	/// cathched.
	/// </remarks>
	public class EventSink: Constants
	{
		public bool EventHandlerCalled;
		
		public void EventHandler(object sender, EventArgs e)
		{
			EventHandlerCalled = true;
		}
		
		public bool VirtualEventHandlerCalled;
		
		public virtual void VirtualEventHandler(object sender, EventArgs e)
		{
			VirtualEventHandlerCalled = true;
		}
		
		public bool CustomEventHandlerCalled;
		
		public void CustomEventHandler(object sender, CustomEventArgs e)
		{
			CustomEventHandlerCalled = true;
		}
		
		public bool VoidHandlerCalled;
		
		public void VoidHandler()
		{
			VoidHandlerCalled = true;
		}
		
		public bool VoidHandler2Called;
		
		public void VoidHandler2(object sender, EventArgs e)
		{
			VoidHandler2Called = true;
		}
		
		public bool VoidHandler5Called;
		
		public void VoidHandler5(object sender, string arg2, int arg3, DateTime arg4, float arg5)
		{
			Assert.AreEqual(Argument2, arg2);
			Assert.AreEqual(Argument3, arg3);
			Assert.AreEqual(Argument4, arg4);
			Assert.AreEqual(Argument5, arg5);
			VoidHandler5Called = true;
		}
		
		public bool StringHandlerCalled;
		
		public string StringHandler()
		{
			StringHandlerCalled = true;
			return "StringHandler";
		}
		
		public bool StringHandler2Called;
		
		public string StringHandler2(object sender, EventArgs e)
		{
			StringHandler2Called = true;
			return "StringHandler2";
		}
		
		public bool StringHandler5Called;
		
		public string StringHandler5(object sender, string arg2, int arg3, DateTime arg4, float arg5)
		{
			Assert.AreEqual(Argument2, arg2);
			Assert.AreEqual(Argument3, arg3);
			Assert.AreEqual(Argument4, arg4);
			Assert.AreEqual(Argument5, arg5);
			StringHandler5Called = true;
			return "StringHandler5";
		}
		
		public bool DoubleHandlerCalled;
		
		public double DoubleHandler()
		{
			DoubleHandlerCalled = true;
			return -1.0;
		}
		
		public bool DoubleHandler2Called;
		
		public double DoubleHandler2(object sender, EventArgs e)
		{
			DoubleHandler2Called = true;
			return -2.0;
		}
		
		public bool DoubleHandler5Called;
		
		public double DoubleHandler5(object sender, string arg2, int arg3, DateTime arg4, float arg5)
		{
			Assert.AreEqual(Argument2, arg2);
			Assert.AreEqual(Argument3, arg3);
			Assert.AreEqual(Argument4, arg4);
			Assert.AreEqual(Argument5, arg5);
			DoubleHandler5Called = true;
			return -3.0;
		}
		
		public bool PointFHandlerCalled;
		
		public PointF PointFHandler()
		{
			PointFHandlerCalled = true;
			return new PointF(-1.0f, 3.0f);
		}
		
		public bool PointFHandler2Called;
		
		public PointF PointFHandler2(object sender, EventArgs e)
		{
			PointFHandler2Called = true;
			return new PointF(-2.0f, 3.0f);
		}
		
		public bool PointFHandler5Called;
		
		public PointF PointFHandler5(object sender, string arg2, int arg3, DateTime arg4, float arg5)
		{
			Assert.AreEqual(Argument2, arg2);
			Assert.AreEqual(Argument3, arg3);
			Assert.AreEqual(Argument4, arg4);
			Assert.AreEqual(Argument5, arg5);
			PointFHandler5Called = true;
			return new PointF(-3.0f, 3.0f);
		}
		
		// Static handler - must NEVER be called, all throw exceptions
		public static void StaticEventHandler(object sender, EventArgs e)
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static void StaticCustomEventHandler(object sender, CustomEventArgs e)
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static void StaticVoidHandler()
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static void StaticVoidHandler2(object sender, EventArgs e)
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static void StaticVoidHandler5(object sender, string arg2, int arg3, DateTime arg4, float arg5)
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static string StaticStringHandler()
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static string StaticStringHandler2(object sender, EventArgs e)
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static string StaticStringHandler5(object sender, string arg2, int arg3, DateTime arg4, float arg5)
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static double StaticDoubleHandler()
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static double StaticDoubleHandler2(object sender, EventArgs e)
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static double StaticDoubleHandler5(object sender, string arg2, int arg3, DateTime arg4, float arg5)
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static PointF StaticPointFHandler()
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static PointF StaticPointFHandler2(object sender, EventArgs e)
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}
		
		public static PointF StaticPointFHandler5(object sender, string arg2, int arg3, DateTime arg4, float arg5)
		{
			throw new InvalidOperationException("Static handlers must not be called.");
		}

#if !NET11
		public bool PropertyChangedCalled;
		
		public void PropertyChangedEventHandler(object sender, EventArgs e)
		{
			PropertyChangedCalled = true;
		}
#endif
	}
}

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
Web Developer
Russian Federation Russian Federation
I'm a system administrator from Moscow, Russia. Programming is one of my hobbies. I presume I'm one of the first Russians who created a Web site dedicated to .Net known that time as NGWS. However, the Web page has been abandoned a long ago.

Comments and Discussions