IoC and Unity - Configuration Changes for the Better

In my previous post about Unity and IoC containers, I made note of some changes in the latest drop of the Unity Application Block.  As Grigori Melnik, the PM of the Unity and Enterprise Library team noted, Unity should be released in its final form on April 7th, so stay tuned.  In the mean time, the latest drop of Unity was on March 24th, so go ahead and it pick it up.

Configuration Changes

As I noted from above, the public APIs really haven't changed all that much.  Instead, most of the efforts recently have been around performance improvements in the ObjectBuilder base and the configuration of the container itself.  I must admit that previous efforts left me a little cold with having to decorate my classes with the DependencyAttribute.  Well, you shouldn't have to do that anymore, now that the TypeInjectionElement has been added so that you can map your constructor arguments and so on.  Let's walk through a simple example of doing so.

First, let's go through my basic anti-corruption container that I use for Unity and any other container that I use for registration and so on.

namespace UnitySamples

{

    public static class IoC

    {

        private static IDependencyResolver resolver;

 

        public static void Initialize(IDependencyResolver resolver)

        {

            IoC.resolver = resolver;

        }

 

        public static T Resolve<T>()

        {

            return resolver.Resolve<T>();

        }

 

        public static T Resolve<T>(string name)

        {

            return resolver.Resolve<T>(name);

        }

    }

}


Remember this is just a quick spike sample of my anti-corruption container which was taken from Ayende.  And then in order to configure my UnityContainer through the implementation of my IDependencyResolver interface.  Let's take a brief look at that:

namespace UnitySamples

{

    public interface IDependencyResolver

    {

        T Resolve<T>(string name);

 

        T Resolve<T>();

    }

}


And then the implementation of the interface for Unity would look like:

using System.Configuration;

using Microsoft.Practices.Unity;

using Microsoft.Practices.Unity.Configuration;

 

namespace UnitySamples

{

    public class UnityDependencyResolver: IDependencyResolver

    {

        private IUnityContainer container;

 

        public UnityDependencyResolver()

        {

            container = new UnityContainer();

            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

            section.Containers.Default.Configure(container);

        }

 

        public T Resolve<T>()

        {

            return container.Resolve<T>();

        }

 

        public T Resolve<T>(string name)

        {

            return container.Resolve<T>(name);

        }

    }

}


Now, if you look at the constructor for the UnityDependencyResolver above, I am using the default container in order to configure my container.  But, I have the option of specifying a name for it as well or even just an index.  I could just easily change that code to this and it would work if I name my container default.  This is a little bit of a change from before when I had to use the GetConfigCommand() method in order to configure the container which was a bit too chatty for my tastes.

            container = new UnityContainer();

            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

            section.Containers["default"].Configure(container);


So, the idea that I want to do is create an object graph so that I have classes with dependencies that have dependencies.  Without doing AOP and some basic interception, we could take the approach of keeping around something like an IContext which would have our cross-cutting concerns in one location such as logging and whatnot in one area so your objects don't sit there with 16 constructor parameters, and instead has a context from which it can pull.  This approach has worked for me in the past, so let's just go through that one right now.

First, let's look at the context that has those cross-cutting concerns and the actual implementation:

namespace UnitySamples

{

    public interface IContext

    {

        ILogger Logger { get; }

    }

}


And then the concrete implementation might look something like this:

namespace UnitySamples

{

    public class UnityContext : IContext

    {

        private readonly ILogger logger;

 

        public UnityContext(ILogger logger)

        {

            this.logger = logger;

        }

 

        public ILogger Logger

        {

            get { return logger; }

        }

    }

}


So, what I do here is inject my logger into my context, and probably anything else that might be cross-cutting as well.  So, now in one of my classes, then I can accept the IContext in to do what I need it to do.  That would look something like this.

namespace UnitySamples

{

    public class Customer

    {

        public string CustomerId { get; set; }

 

        public string FirstName { get; set; }

 

        public string MiddleName { get; set; }

 

        public string LastName { get; set; }

    }

 

    public class CustomerTasks

    {

        private readonly IContext context;

 

        public CustomerTasks(IContext context)

        {

            this.context = context;

        }

 

        public void SaveCustomer(Customer customer)

        {

            // Save customer

            context.Logger.LogEvent("Saving customer", LogLevel.Information);

        }

    }

}


I'm not doing anything special, instead, just showing how this pattern might apply.  And then just tying it all together is my console application (sometimes my favorite UI for quick spikes).

namespace UnitySamples

{

    class Program

    {

        static void Main(string[] args)

        {

            IoC.Initialize(new UnityDependencyResolver());

            CustomerTasks tasks = IoC.Resolve<CustomerTasks>();

            tasks.SaveCustomer(new Customer{ CustomerId = "12345", FirstName = "Joe", LastName = "Smith", MiddleName = "Frank"});

        }

    }

}


But the more interesting part about this is the XML configuration.  I know many people such as Ayende have declared war on XML configuration, but I think for this quick example it does quite well.  If we start talking about complex object graphs, then I'd certainly agree and I'd rather do it programmatically.  But, let's first look at how I'd wire up the whole thing in the app.config file.

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <configSections>

        <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />

    </configSections>

 

    <unity>

        <typeAliases>

            <typeAlias alias="string" type="System.String, mscorlib" />

            <typeAlias alias="ILogger" type="UnitySamples.ILogger, UnitySamples" />

            <typeAlias alias="ConsoleLogger" type="UnitySamples.ConsoleLogger, UnitySamples" />

            <typeAlias alias="DebugLogger" type="UnitySamples.DebugLogger, UnitySamples" />

            <typeAlias alias="IContext" type="UnitySamples.IContext, UnitySamples" />

            <typeAlias alias="UnityContext" type="UnitySamples.UnityContext, UnitySamples" />

            <typeAlias alias="CustomerTasks" type="UnitySamples.CustomerTasks, UnitySamples" />

        </typeAliases>

        <containers>

            <container>

                <types>

                    <type type="ILogger" mapTo="ConsoleLogger" name="defaultLogger"/>

                    <type type="ILogger" mapTo="DebugLogger" name="debugLogger"/>

                    <type type="IContext" mapTo="UnityContext">

                        <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">

                            <constructor>

                                <param name="logger" parameterType="ILogger">

                                    <dependency name="debugLogger"/>

                                </param>

                            </constructor>

                        </typeConfig>

                    </type>

                    <type type="CustomerTasks">

                        <typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">

                            <constructor>

                                <param name="context" parameterType="IContext">

                                    <dependency/>

                                </param>

                            </constructor>

                        </typeConfig>

                    </type>

                </types>

            </container>

        </containers>

    </unity>

</configuration>


As you may notice from above, Unity gives us the ability to give type aliases so that we can reference the short names instead of the long ugly fully qualified type names by using the <typeAliases><typeAlias> nodes in the configuration.  Much as before, we still register our types with a name, type and so on. 

But, what's interesting is that we now have the ability to do type injection through a Unity extension called the TypeInjectionElement.  This allows us to inject into the constructor and put in our parameters as need be.  But we could also replace that with <method> or <property> in order to do method injection and property setter injection respectively. 
Within the <param> element, we can specify our given injection element parameters.  This allows us to specify the name of our given parameter, the type, but also for the dependency check, we can specify the name and type to alias the other <type> elements that we wish to get a reference of.  We can also specify the values if we so desire of strings, integers and so on.  Below is a simple example of using both dependency references and values.

<constructor>

    <param name="logger" parameterType="ILogger">

        <dependency name="debugLogger"/>

    </param>

    <param name="dbName" parameterType="string">

        <value value="AdventureWorks" />

    </param>

</constructor>


I find the best way to learn about these features usually isn't through documentation, although it's a nice thing to do, but instead the tests.  I look for the functionality that I'm interested in and go deep.  A project this size without good unit tests == FAIL in my opinion.  Anyhow, this is better looking than it used to be and much more intuitive.

Interception Revisited

As Chris Tavares, the developer of Unity noted on my blog before was the fact that he could easily put in the interceptors from the ObjectBuilder2 since ObjectBuilder2 is modular and Unity is built upon it.  It shouldn't have been news, because I've been working on that myself to get lightweight interception to work on it.  Maybe when I get it fully implemented I'll share it.  But in the mean time, it's just a spike.

Conclusion

I think this approach has helped in the XML configuration goo that had been a bit confusing.  I didn't want to clutter my domain models and processing code with excess attributes stating intent, and would rather keep it clean.  This makes a step in that direction.  In the next installation of looking at IoC will revolve around Spring.NET and AOP in the Enterprise, so stay tuned...  Until next time...

kick it on DotNetKicks.com

6 Comments

Comments have been disabled for this content.