Using using to unbind event handlers

Dynamically binding event handlers is a common source of bugs, and memory leaks.

The traditional approach is to use a finally block:

	EventHandler eventHandler = (s, e) => fooService.Bar();
	eventSource.AnEvent += eventHandler;
	try
	{
		// do something that raises the event
	} 
	finally
	{
		eventSource.AnEvent -= eventHandler;
	}

An alternative way to ensure that your handler is always unbound correctly is to (ab)use IDisposable (again!) and use the using sugar:

		using (_eventHandlerFactory.Attach(_eventSource, _fooService))
		{
			// do something that raises the event
		}
	public class EventHandlerFactory
	{
		public IDisposable Attach(IEventSource eventSource, IFooService fooService)
		{
			EventHandler eventHandler = (s, e) => fooService.Bar();
			eventSource.AnEvent += eventHandler;
			return new EventHandlerCookie(eventSource, eventHandler);
		}

		private class EventHandlerCookie : IDisposable
		{
			private readonly IEventSource _eventSource;
			private readonly EventHandler _eventHandler;

			public EventHandlerCookie(IEventSource eventSource, EventHandler eventHandler)
			{
				_eventSource = eventSource;
				_eventHandler = eventHandler;
			}

			public void Dispose()
			{
				_eventSource.AnEvent -= _eventHandler;
			}
		}
	}

	public interface IFooService 
	{
		void Bar();
	}

	public interface IEventSource 
	{
		event EventHandler AnEvent;
	}

	[TestFixture]
	public class EventHandlerFactoryTests
	{
		private IEventSource _eventSource = MockRepository.GenerateStub<IEventSource>();
		private IFooService _fooService = MockRepository.GenerateStub<IFooService>();
		private EventHandlerFactory _eventHandlerFactory;

		[SetUp]
		public void SetUp()
		{
			_eventHandlerFactory = new EventHandlerFactory();
		}

		[Test]
		public void Event_handler_is_attached()
		{		
			_eventHandlerFactory.Attach(_eventSource, _fooService);
			_eventSource.Raise(es => es.AnEvent += null, _eventSource, EventArgs.Empty);

			_fooService.AssertWasCalled(fs => fs.Bar());
		}

		[Test]
		public void Event_handler_is_detached_when_disposed()
		{
			using (_eventHandlerFactory.Attach(_eventSource, _fooService))
			{
				_eventSource.Raise(es => es.AnEvent += null, _eventSource, EventArgs.Empty);
			}
			_eventSource.Raise(es => es.AnEvent += null, _eventSource, EventArgs.Empty);

			_fooService.AssertWasCalled(fs => fs.Bar(), o => o.Repeat.Once());
		}
	}

A better XmlWriter

I’m not a huge fan of the XmlWriter API. In particular, remembering to close every tag.

It would be nice to have something like Haml, where the nesting takes care of it. A bit tricky in C#, but you can get some of the effect by (ab)using IDisposable:

public class SelfClosingXmlWriter
{
    private readonly XmlWriter _xmlWriter;

    public SelfClosingXmlWriter(XmlWriter xmlWriter)
    {
        _xmlWriter = xmlWriter;
    }

    public XmlElementCookie WriteStartElement(string localName)
    {
        _xmlWriter.WriteStartElement(localName);
        return new XmlElementCookie(_xmlWriter);
    }

    public XmlAttributeCookie WriteStartAttribute(string localName)
    {
        _xmlWriter.WriteStartAttribute(localName);
        return new XmlAttributeCookie(_xmlWriter);
    }

    public void WriteRaw(string xml)
    {
        _xmlWriter.WriteRaw(xml);
    }

    public void WriteString(string xml)
    {
        _xmlWriter.WriteString(xml);
    }

    public void WriteAttributeString(string localName, string value)
    {
        _xmlWriter.WriteAttributeString(localName, value);
    }

    public class XmlElementCookie : IDisposable
    {
        private readonly XmlWriter _xmlWriter;

        public XmlElementCookie(XmlWriter xmlWriter)
        {
            _xmlWriter = xmlWriter;
        }

        public void Dispose()
        {
            _xmlWriter.WriteEndElement();
        }
    }

    public class XmlAttributeCookie : IDisposable
    {
        private readonly XmlWriter _xmlWriter;

        public XmlAttributeCookie(XmlWriter xmlWriter)
        {
            _xmlWriter = xmlWriter;
        }

        public void Dispose()
        {
            _xmlWriter.WriteEndAttribute();
        }
    }
}

Which lets you go from this:

var writer = XmlWriter.Create("out.xml", settings);
writer.WriteStartElement("book");
writer.WriteStartElement("author");
writer.WriteStartElement("name");
writer.WriteString("Big John");
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteStartElement("title");
writer.WriteString("Amazing Cakes!");
writer.WriteEndElement();
writer.WriteEndElement();

To this:

var writer = new SelfClosingXmlWriter(XmlWriter.Create("out.xml", settings));
using (writer.WriteStartElement("book"))
{
    using (writer.WriteStartElement("author"))
    {
        using (writer.WriteStartElement("name"))
        {
            writer.WriteString("Big John");
        }
    }
    using (writer.WriteStartElement("title"))
    {
        writer.WriteString("Amazing Cakes!");
    }
}

Stop… system time!

Writing tests for code that deals with time is always tricky, and Ayende’s solution is probably the most elegant around. There’s always room for some syntactic sugar though!

using System;
using NUnit.Framework;

namespace Your.Namespace.Here
{
	public class SystemTime : IDisposable
	{
		private static readonly Func<DateTime> GetDateTimeNow = () => DateTime.Now;
		private static readonly Func<DateTime> GetUtcNow = () => DateTime.UtcNow;

		public static Func<DateTime> Now = GetDateTimeNow;
		public static Func<DateTime> UtcNow = GetUtcNow;

		public static void Reset()
		{
			Now = GetDateTimeNow;
			UtcNow = GetUtcNow;
		}

		private SystemTime(DateTime now)
		{
			Now = () => now;
		}

		public void Dispose()
		{
			Reset();
		}

		public static SystemTime Is(DateTime dateTime)
		{
			return new SystemTime(dateTime);
		}
	}

	public class Examples
	{
		[Test]
		public void Change_time()
		{
			var bohemiaAdoptsTheGregorianCalendar  = new DateTime(1584, 1, 17);
			using(SystemTime.Is(bohemiaAdoptsTheGregorianCalendar))
			{
				Assert.That(SystemTime.Now(), Is.EqualTo(bohemiaAdoptsTheGregorianCalendar));
				// do something
			}
			Assert.That(SystemTime.Now(), Is.EqualTo(DateTime.Now));
		}
	}
}

And yes, I do like using dates from history :)