Getting the type being constructed when using a factory method

When registering a type to be constructed by a factory method, it is sometimes important to know what type the instance is being constructed for.

For example, when using log4net you might want to inject a logger for that specific type.

I knew how to do it using StructureMap:

For<ILog>().Use(s => LogManager.GetLogger(s.Root.ConcreteType));

But today I had to work out how to do it with Castle. (It’s pretty similar).

Component.For<ILog>().UsingFactoryMethod((k, cm, cc) => LogManager.GetLogger(cc.Handler.Service))

Using named instances as constructor arguments

I’ve previously discussed the usefulness of StructureMap’s named instances, as well as bemoaning how fugly the syntax is for using them:

For<IUserRepository>()
    .Ctor<ISession>("session").Use(c => c.GetInstance<ISession>("UserDB"));

I submitted a pull request to improve it, but the other day I realised I could fix it in the current version with an extension method:

public static class StructureMapExtensions
{
    public static SmartInstance<T> Named<T, CTORTYPE>(this SmartInstance<T>.DependencyExpression<CTORTYPE> instance, string name)
    {
        return instance.Is(c => c.GetInstance<CTORTYPE>(name));
    }
}

Which means you can say:

For<IUserRepository>()
    .Ctor<ISession>("session").Named("UserDB");

Yay!

StructureMapAssert

Following on from a previous post, here’s an updated set of StructureMap assertions:

public static class StructureMapAssert
{
	public static void AssertSingleton<T>(this IContainer container)
	{
		var instance1 = AssertResolvable<T>(container);
		var instance2 = AssertResolvable<T>(container);
		Assert.That(instance1, Is.SameAs(instance2));
	}

	public static void AssertTransient<T>(this IContainer container)
	{
		var instance1 = AssertResolvable<T>(container);
		var instance2 = AssertResolvable<T>(container);
		Assert.That(instance1, Is.Not.SameAs(instance2));
	}

	public static void AssertHttpRequestScoped<T>(this IContainer container)
	{
		T instance2;
		using (new MockHttpContext())
		{
			var instance1 = AssertResolvable<T>(container);
			instance2 = AssertResolvable<T>(container);
			Assert.That(instance1, Is.SameAs(instance2));
		}
		var instance3 = AssertResolvable<T>(container);
		Assert.That(instance3, Is.Not.SameAs(instance2));
	}

	private static T AssertResolvable<T>(this IContainer container)
	{
		try
		{
			return container.GetInstance<T>();
		}
		catch (Exception)
		{
			Console.WriteLine(container.WhatDoIHave());
			throw;
		}
	}

	private class MockHttpContext : IDisposable
	{
		private readonly StringWriter _stringWriter;
		private readonly HttpContext _httpContext;

		public MockHttpContext()
		{
			_httpContext = HttpContext.Current;
			var httpRequest = new HttpRequest("test.aspx", "http://localhost", "?a=1&amp;b=2");
			_stringWriter = new StringWriter();
			var httpResponse = new HttpResponse(_stringWriter);
			HttpContext.Current = new HttpContext(httpRequest, httpResponse);
		}

		public void Dispose()
		{
			_stringWriter.Dispose();
			HttpContext.Current = _httpContext;
		}
	}
}
public class RegistryTests
{
    private IContainer container;
    [TestFixtureSetUp]
    public void FixtureSetUp()
    {
        container = BootstrapContainer();
    }

    [Test]
    public void SessionFactory()
    {
        container.AssertSingleton<ISessionFactory>();
    }

    [Test]
    public void Session()
    {
        container.AssertHttpRequestScoped<ISession>();
    }

    [Test]
    public void ThingyRepository()
    {
        container.AssertTransient<IThingyRepository>();
    }
}

Managing multiple Session Factories using named instances

If you are using NHibernate for data access, and have to access more than one database, then you need a way of managing multiple Session Factories.

Ideally, your repositories (or whatever) would only take a dependency on an ISession, without needing to know where it came from (DIP). But if you’re getting these repositories out of a container, then you have a problem. How do you provide a different ISession to different instances?

One solution is to use named instances. The following example is for StructureMap, other containers are available. :)

public class NHibernateRegistry : Registry
{
    public NHibernateRegistry()
    {
        const string connectionString1 = "theNameOfAConnectionStringInAppConfig";
        const string connectionString2 = "theNameOfADifferentConnectionStringInAppConfig";

        For<ISessionFactory>()
            .Singleton()
            .Use(SessionFactory.BuildFor(connectionString1))
            .Named(connectionString1);

        For<ISessionFactory>()
            .Singleton()
            .Use(SessionFactory.BuildFor(connectionString2))
            .Named(connectionString2);

        For<ISession>()
            .Use(c => c.GetInstance<ISessionFactory>(connectionString1).OpenSession())
            .Named(connectionString1);

        For<ISession>()
            .Use(c => c.GetInstance<ISessionFactory>(connectionString2).OpenSession())
            .Named(connectionString2);

        For<ISomethingRepository>()
            .Ctor<ISession>("session").Use(c => c.GetInstance<ISession>(connectionString1));

        For<ISomethingElseRepository>()
            .Ctor<ISession>("session").Use(c => c.GetInstance<ISession>(connectionString2));
    }
}

Or maybe, in the future, just:

For<ISomethingElseRepository>()
    .Ctor<ISession>("session").Named(connectionString2);

Register concrete types against the first interface

Most of my IoC experience has been using StructureMap, with the default conventions:

container.Configure(c => c.Scan(s =>
    {
        s.Assembly(GetType().Assembly);
        s.LookForRegistries();
        s.WithDefaultConventions();
    }));

Which registers any components whose name matches the interface, minus the I, e.g. ThingyController : IThingyController, but not DefaultThingyRepository : IThingyRepository.

Recently however, I’ve worked on a few projects using Castle Windsor, whose auto-registration uses the first interface:

 container.Register(AllTypes
    .FromAssembly(GetType().Assembly)
    .Pick()
    .WithService.FirstInterface()
    .Configure(req => req.LifeStyle.Transient));

What a great idea, I thought! Why can’t I do that with StructureMap? Well the short answer is, you can:

container.Configure(c => c.Scan(s =>
    {
        s.Assembly(GetType().Assembly);
        s.LookForRegistries();
        s.RegisterConcreteTypesAgainstTheFirstInterface();
    }));

Hurray!

Releasing http scoped objects when using OpenRasta with StructureMap

StructureMap isn’t quite as pro-active as Castle Windsor when it comes to releasing (and disposing) of http scoped objects. So it’s generally a good practice to do so explicitly at the end of a web request:

protected void Application_EndRequest(object sender, EventArgs e)
{
    ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}

My first attempt to reproduce this with OpenRasta used a pipeline contributor:

using OpenRasta.Pipeline;
using OpenRasta.Web;
using StructureMap.Pipeline;

namespace OpenRasta.DI.StructureMap.Pipeline.Contributors
{
	public class ReleaseAndDisposeAllHttpScopedObjects : IPipelineContributor
	{
		public void Initialize(IPipeline pipelineRunner)
		{
			pipelineRunner.Notify(ReleaseAndDispose)
				.After<KnownStages.IOperationExecution>()
				.And.Before<KnownStages.IOperationResultInvocation>();
		}

		private static PipelineContinuation ReleaseAndDispose(ICommunicationContext communicationContext)
		{
			HttpContextLifecycle.DisposeAndClearAll();
			return PipelineContinuation.Continue;
		}
	}
}

Thankfully, Seb pointed out that it made more sense to hook into IDependencyResolver.HandleIncomingRequestProcessed():

public void HandleIncomingRequestProcessed()
{
    HttpContextLifecycle.DisposeAndClearAll();
}

Testing the lifecycle of components

When using an IoC container I like to have confidence that I can retrieve the components that I think I can (rather than getting an unpleasant surprise at runtime!).

This generally involves bootstrapping the container and writing (integration) tests that resolve the types I need. You won’t generally need a test for every class, as retrieving a root object will fail if any of its dependencies cannot be resolved.

While this is a good start, it’s also useful to test the lifecycle of registered components. For example, you want to ensure that your SessionFactory is a singleton. This calls for some helper assertions! (The examples below are tailored for StructureMap, other containers are available :)

using NUnit.Framework;

namespace Your.Namespace.Here
{
	public class TestingComponentLifecycles
	{
		private IContainer container;

		[TestFixtureSetUp]
		public void FixtureSetUp()
		{
			container = BootstrapContainer();
		}

		[Test]
		public void SessionFactory()
		{
			AssertSingleton<SessionFactory>();
		}

		[Test]
		public void Frobulator()
		{
			AssertTransient<Frobulator>();
		}

		private void AssertSingleton<T>()
		{
			var instance1 = container.Resolve<T>();
			var instance2 = container.Resolve<T>();
			Assert.That(instance1, Is.SameAs(instance2));
		}

		private void AssertTransient<T>()
		{
			var instance1 = container.Resolve<T>();
			var instance2 = container.Resolve<T>();
			Assert.That(instance1, Is.Not.SameAs(instance2));
		}
	}
}