Agnostic IoC Pt II – Container Self Registration

So – here is the second in the series of introducing Agnostic IoC. In this topic I wanted to cover a standard problem that (particularly as developers of a proprietary system such as Sitecore) face regularly.

I have always (for convenience as much as anything) utilised the global.asax.cs to perform my container setup. This is particularly easy as I usually have this class inherit an interface. This conveniently allows me to cast the application instance as my ‘IContainerAccessor’ to allow me to get at the container. This (for Sitecore / Umbraco) in particular is inherently flawed in that, the vendors of third party systems also often mess with these classes – Sitecore for example (off the top of my head) have changed it in 2 or 3 of the last major releases and possibly some of the minors. I have seen (in implementations such as Glass Mapper), the use of WebActivator to overcome this too – this is a perfectly reasonable alternative.

In designing Agnostic IoC, I wanted to consider the possibility of having Agnostic scan the loaded assemblies for containeradapters and register them for itself, here is an example of the test container adapter we are going to use.

    public class TestStructureMapContainerAdapter : StructureMapContainerAdapter
    {
        public override void RegisterComponents()
        {
            Container.Configure(x => x.For<IDependantClass>().Use<DependantClass>());

            Container.Configure(x => x.For<IDependantClass>().Use<DependantClass>().Named("DependentClass3"));

            // Agnostic IoC Registration
            // Register<IDependantClass>();
        }
    }

Note in the example above, we are using the native container registration, you could as is shown in the comments, utilise the Agnostic registrations instead.

Assembly scanning / container adapter provision is done by means of a factory class, this is dependency injected into the ContainerManager class if you don’t like the default implementation by inheriting from either the default ContainerAdapterFactory and overriding the approriate method or simply implementing IContainerAdapterFactory.

The first time you use a ContainerManager, it will (unless you have injected your own container), attempt to scan the loaded assemblies for all classes inheriting from IContainerAdapter and register them with the adapter factory. This means that when you instantiate the container manager (with or without name), it simply ‘looks it up’ from the factory and returns you the appropriate one. This only happens when you first instantiate the first container manager meaning that whenever you are ready to use the Container it will load and sort itself out. No need for Web Activator or global. This also has the inherent value that in unit tests, the registration is done similarly, so no test fixture setup / tear down type affair, you can simply create different adapters for different uses and refer to them by name (usually on a constant for convenience).

Agnostic IoC by default registers container adapters with an empty string for a name, and if not explicitly told to, the ContainerManager class will use the empty string variant by default. If you want to to keep container separate, simply override the name property and use the same name when instantiating the ContainerManager

    public override string Name
    {
       get { return TestConstants.StructureMapContainerName; }
    }

As always, if you wish to register your own container for use with Agnostic – you have to inject the container into the ContainerManager (again with an optional key), with a wrapping adapter class, like so.

    IWindsorContainer container = new WindsorContainer();
    IContainerAdapter adapter = new WindsorContainerAdapter(container);

Container Manager Factory
As with many closed proprietary systems such as Sitecore, you will find occasions where you need to use your IoC container from a parameterless constructor. Agnostic IoC
supports this by means of a static ContainerManagerFactory, this can be used to drive your class implementation in construction.

	var containerManager = ContainerManagerFactory.GetContainerManager(TestConstants.WindsorContainerName);

Used with a parameterless constructor becomes:

	public class MyClass
	{
		public MyClass() : this(ContainerManagerFactory.GetContainerManager(TestConstants.WindsorContainerName).Resolve())
		{
		}

		public MyClass(IMyInterface dependency)
		{
		}
	}

For the Sitecore guys, this is PARTICULARLY useful for pipelines / commands.

Conclusion
So there you have it – Container Self Registration with Agnostic IoC. As always, different IoC containers can live side by side. As this is the second post in the series, I invite you to give it a try or even just give feedback on the concept – particularly those of you, who like me, build add ons for Sitecore.
Related Articles

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s