IoC and the Unity Application Block Once Again

Update:  Fixed code changed from CTP and More in the series:
After the reaction of my last post of talking about IoC and the Unity Application Block, I thought I'd include a few more samples of using Unity and how they compare with other IoC containers.  I realized after my first one, that I didn't give any love to StructureMap and I'm going to fix that for a brief sample as well.  I realize there are plenty of IoC containers out there including Spring, but quite frankly I've found it heavier than most, so I'm going to stick with Unity, Castle Windsor and StructureMap for this example.

Before I continue, check out David Hayden's screencast of IoC with ASP.NET MVC for some more interesting ideas regarding IoC and Unity.

Setter Injection versus Constructor Injection

I've been down the road of constructor injection versus setter injection.  My opinion is that you try to inject the most you can through your constructor such as in a Model View Presenter, injecting the View and the Service Layer.  Now, you may have cross-cutting concerns such as logging that you may want to swap out, but putting it in the constructor can just get ugly and you can set a default logger in your class anyways such as a NullLogger.  Martin Fowler, as always, covers this topic here and it's quite interesting as it is an open debate.

The other option I've done down this road was to create an IContext interface which is injected through the constructor that has some of the cross-cutting concerns wrapped up into it, but for now, let's just walk through a sample of having setter injection as well. 

Get Down to Details

Now that we got all the other stuff out of the way, let's go ahead and set up some basic examples in Unity, Castle Windsor and StructureMap doing setter injection.  I'll basically take the code from last time and apply it here as well.  So, let's start out with the Unity Application Block Sample:

namespace UnitySamples

{

    public interface ILogger

    {

        void Log(string message);

    }

}


And we have two implementations, the NullLogger (the default) and the ConsoleLogger (the override).  Let's go through each of those.

namespace UnitySamples

{

    public class NullLogger : ILogger

    {

        public void Log(string message)

        {

            // Do nothing

        }

    }

}


using System;

 

namespace UnitySamples

{

    public class ConsoleLogger : ILogger

    {

        public void Log(string message)

        {

            Console.WriteLine(message);

        }

    }

}


Now that I have these two implementations, I won't bother repeating these for the others unless they specifically change, which they shouldn't.  Now, to my implementation details of my CustomerTasks object.

using Microsoft.Practices.Unity;

 

namespace UnitySamples

{

    public class CustomerTasks

    {

        private ILogger logger = new NullLogger();

 

        [Dependency]

        public ILogger Logger

        {

            get { return logger; }

            set { logger = value; }

        }

 

        public void SaveCustomer()

        {

            Logger.Log("Saved customer");

        }

    }

}


As you may note, I set the default implementation of my logger to a NullLogger because by default, I don't care about logging, so it's about the same as a NoOp.  But, if I want to change that, I can through my setter injection.  This goes for any cross-cutting concern.  I also marked my Logger property with the DependencyAttribute which basically says that give me the ILogger instance registered when you go through the container to create it.  This of course requires class modification, so it's not a simple rip and replace as it was with constructor injection.  So, now let's look at the implementation of our configuration, much as before.

using System.Configuration;

using Microsoft.Practices.Unity;

using Microsoft.Practices.Unity.Configuration;

 

namespace UnitySamples

{

    class Program

    {

        static void Main(string[] args)

        {

            IUnityContainer container = new UnityContainer();

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

            section.Containers.Default.GetConfigCommand().Configure(container);

            CustomerTasks tasks1 = container.Resolve<CustomerTasks>();

            CustomerTasks tasks2 = container.Resolve<CustomerTasks>();

            tasks1.SaveCustomer();

            tasks2.SaveCustomer();  

        }

    }

}


And the configuration file will look much like before as:

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

<configuration>

  <configSections>

    <section name="unity"

            type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,

                  Microsoft.Practices.Unity.Configuration" />

  </configSections>

  <unity>

    <containers>

      <container>

        <types>

          <type type="UnitySamples.ILogger,UnitySamples"

                mapTo="UnitySamples.ConsoleLogger,UnitySamples"

                lifetime="Singleton"/>

        </types>

      </container>

    </containers>

  </unity>

</configuration>


Now, let's do the same thing with Castle Windsor.  Most of the code will be the same from our Unity sample as I can't imagine that much will change except that I don't need to register the DependencyAttribute on the CustomerTasks object.  Let's first look at the changed CustomerTasks object.

namespace CastleSamples

{

    public class CustomerTasks

    {

        private ILogger logger = new NullLogger();

 

        public ILogger Logger

        {

            get { return logger; }

            set { logger = value; }

        }

 

        public void SaveCustomer()

        {

            Logger.Log("Saved customer");

        }

    }

}


Now, let's look at the program.cs file to see how really nothing changed at all from our perspective:

using Castle.Windsor;

using Castle.Windsor.Configuration.Interpreters;

 

namespace CastleSamples

{

    class Program

    {

        static void Main(string[] args)

        {

            WindsorContainer container = new WindsorContainer(new XmlInterpreter());

            CustomerTasks tasks1 = container.Resolve<CustomerTasks>();

            CustomerTasks tasks2 = container.Resolve<CustomerTasks>();

            tasks1.SaveCustomer();

            tasks2.SaveCustomer();

        }

    }

}


And then our config file looks like this:

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

<configuration>

  <configSections>

    <section name="castle"

        type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />

  </configSections>

  <castle>

    <components>

      <component id="customertasks" type="CastleSamples.CustomerTasks, CastleSamples" lifestyle="transient" />

      <component id="logger.console" service="CastleSamples.ILogger, CastleSamples" type="CastleSamples.ConsoleLogger, CastleSamples" lifestyle="singleton" />

    </components>

  </castle>

</configuration>


So, in reality, nothing changed from our constructor injection versus our setter injection implementation for Castle Windsor.  That to me is pretty cool...  But, now, let's move our attention to StructureMap.  Let's walk through only the code that has changed.  I'm only going to use the one with the StructureMap.config file and not the fluent interfaces just yet.  I know more of the config file and not enough of the interfaces to be effective.  Let's go through what really changed.  In reality, everything is the same from the Castle Windsor implementation and the StructureMap one except for the Program.cs and the StructureMap.config file, so let's look at the Program.cs first.

using StructureMap;

 

namespace StructureMapSamples

{

    class Program

    {

        static void Main(string[] args)

        {

            CustomerTasks tasks1 = ObjectFactory.GetInstance<CustomerTasks>();

            CustomerTasks tasks2 = ObjectFactory.GetInstance<CustomerTasks>();

            tasks1.SaveCustomer();

            tasks2.SaveCustomer();  

        }

    }

}


And to make sure our object is a singleton, let's make our StructureMap.config file and walk through the details:

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

<StructureMap>

  <PluginFamily Type="StructureMapSamples.ILogger" Assembly="StructureMapSamples" DefaultKey="Console">

    <Interceptors>

      <Interceptor Type="Singleton" />

    </Interceptors>

    <Plugin Assembly="StructureMapSamples" Type="StructureMapSamples.ConsoleLogger" ConcreteKey="Console" />

    </PluginFamily>

  <PluginFamily Type="StructureMapSamples.CustomerTasks" Assembly="StructureMapSamples" DefaultKey="CustomerTasks">

    <Plugin Assembly="StructureMapSamples" Type="StructureMapSamples.CustomerTasks" ConcreteKey="CustomerTasks">

      <Setter Name="Logger" Key="Console" />

    </Plugin>

  </PluginFamily>

</StructureMap>


If you're familiar with StructureMap, the config file should make sense to you as I'm creating an ILogger with the default implementation being the ConsoleLogger and then we make sure it is a singleton through the use of an interceptor.  Then we also do a setter injection through our plugin of the CustomerTasks with setting the Logger property to the key of Console.  Pretty simple and straightforward.

So, as you can see, they are very similar in nature, but attack the problem in different ways.  That's the beauty of it all, just determine your needs and your programming style and then the pick of your IoC container should come into line with that.  These are pretty simple and naive samples, but I just want to whet your appetite to open your mind and look for yourself at these containers for yourself.

AOP with PostSharp and Unity?

Gael Fraiteur recently posted on the altdotnet list about the new release of PostSharp.  Gael blogged about that here.  A couple of things intrigued me about it, including the license change to LGPL for the runtime and GPL for the code.  This requires a commercial license should you want to redistribute it with your application.  But, I'll leave that up to him and the lawyers to figure out. 

But, let's get back to Unity for just a second.  Gael recently announced on the Unity Application Block discussion list about including an extension to support PostSharp which you can find here.  You can find the code in particular to do this, plus the Stoplight sample converted at GoogleCode here under PostSharp4Unity.  Get your favorite SVN client and pull it down.

So, let's take my basic example from above and try to get it using the default constructors instead of the approach of calling the container to get ourselves an instance.  A good approach is to keep the container out of your way and produce cleaner code.  A downside of using IoC containers is that they can litter up your code.  PostSharp4Unity allows us to create an extension for Unity and use our default constructors.

First, let's create a Unity container provider so that we can initialize our container programmatically.  Create a UnityContainerProvider in your project that inherits from the IUnityContainerProvider.  That code should look like this:

using Microsoft.Practices.Unity;

using PostSharp4Unity;

using UnitySamples;

 

namespace UnitySamples

{

    public sealed class UnityContainerProvider : IUnityContainerProvider

    {

        private readonly IUnityContainer container;

 

        public UnityContainerProvider()

        {

            this.container = new UnityContainer()

                .RegisterType<ILogger, ConsoleLogger>(new ContainerControlledLifetimeManager());

        }

 

        public IUnityContainer CurrentContainer

        {

            get { return this.container; }

        }

    }

}


Now we also have to mark our assemblyinfo.cs with our default UnityProviderContainer, so open up your assemblyinfo.cs and put this info in there:

using PostSharp4Unity;

using UnitySamples;

 

[assembly: DefaultUnityContainerProvider(typeof(UnityContainerProvider))]


Ok, done and now we have to mark our class that we want to mark our configurable objects that we want to control with PostSharp.  So, open CustomerTasks and modify it to this:

using Microsoft.Practices.Unity;

using PostSharp4Unity;

 

namespace UnitySamples

{

    [Configurable]

    public class CustomerTasks

    {

        private ILogger logger = new NullLogger();

 

        [Dependency]

        public ILogger Logger

        {

            get { return logger; }

            set { logger = value; }

        }

 

        public void SaveCustomer()

        {

            Logger.Log("Saved customer");

        }

    }

}


So, then our program.cs can look like this now:

namespace UnitySamples

{

    class Program

    {

        static void Main(string[] args)

        {

            CustomerTasks tasks1 = new CustomerTasks();

            CustomerTasks tasks2 = new CustomerTasks();

            tasks1.SaveCustomer();

            tasks2.SaveCustomer();  

        }

    }

}


But, in order for PostSharp to do its magic, we need to make sure it's part of our compilation targets in our .csproj file.  So, I hand munged mine and got it to work like this:

  </PropertyGroup>
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <Import Project="$(PostSharpDirectory)PostSharp.targets" Condition=" Exists('$(PostSharpDirectory)PostSharp.targets') " />
</Project>

Then I'm able to get the magic of PostSharp to do its work.  Pretty slick!

Wrapping It Up

So, I hopefully whetted your appetite for these IoC containers for you to go and do a comparison on your own.  Each container has a different way of configuring itself and each solves a different problem set.  It's up to you to decide which one to use.  Along the way you can have a pretty cool journey though in learning deciding what works for you and what doesn't.  Until next time, and hopefully an F# related post...

kick it on DotNetKicks.com
Published Tuesday, February 26, 2008 6:32 PM by podwysocki
Filed under: , , ,

Comments

# re: IoC and the Unity Application Block Once Again

Tuesday, February 26, 2008 7:56 PM by Jeremy D. Miller

Matthew,

The equivalent Xml markup for StructureMap 2.5 will be considerably more terse.  Even here, you don't have to configure the <Interceptor> node like that.  You could just put a Scope="Singleton" attribute on the <PluginFamily> node.  There's also a [Setter] property that would eliminate the need for the <Setter> Xml.  You can also use the <DefaultInstance> node instead of the full blown <PluginFamily>, <Plugin>, <Instance> bit to collapse most of that down to one single Xml node.

The Setter Injection support in StructureMap *is* clumsy, but I almost feel like that is a point in its favor.  Setter injection is evil and I want it to feel bad.

Part of my mission on StructureMap 2.0 and 2.5 has been to declare war on Xml configuration wherever it can be found until the angle bracket disease is quarantined.

# re: IoC and the Unity Application Block Once Again

Tuesday, February 26, 2008 9:53 PM by podwysocki

Jeremy,

Thanks for the feedback...  I should have realized there's a better way of doing a singleton, but it's the way I've done it in the past.  And good information on collapsing the XML down to the smallest possible footprint.  I'm always for that.

I'd agree that setter injection isn't the most preferred way of configuration due to making it crystal clear what your dependencies are.  In fact, with my cross-cutting concerns, I'd rather stick with an injected IApplicationContext so that I can do things with logging.  But instead of being dogmatic about it, I acknowledged it is there, but I do emphasize or perhaps I should have emphasized constructor injection instead.

Matt

# re: IoC and the Unity Application Block Once Again

Monday, March 3, 2008 7:47 PM by podwysocki

Phillip,

No, I didn't forget you and in fact I've written about it in the past.  Like I said before, there are many IoC containers out there and it's really hard to get my head around each and every one of them.  Each of them tackle the problem in slightly a different way, which is good, because it can suit to different programming styles

# re: IoC and the Unity Application Block Once Again

Tuesday, May 26, 2009 9:45 AM by Software Addicted

From what I see, if you are using Setter Injection approach, Castle is better than Unity because you dont have to change the library code.

# re: IoC and the Unity Application Block Once Again

Thursday, November 1, 2012 11:05 PM by Marlowe

Hi there! This is my first comment here so I just wanted

to give a quick shout out and tell you I really enjoy reading

through your articles. Can you recommend any other blogs/websites/forums that deal with

the same topics? Thanks for your time!

# re: IoC and the Unity Application Block Once Again

Sunday, November 18, 2012 9:02 PM by Ault

i use both gold and silver bracelets because for me, that they have been both

great bracelets to wear;;

# re: IoC and the Unity Application Block Once Again

Sunday, November 25, 2012 7:00 PM by Seward

you can still also give away your baby some antibacterial baby

socks to ensure that your baby is always clean`

# re: IoC and the Unity Application Block Once Again

Thursday, December 20, 2012 6:35 PM by Monson

I visited plenty of website in spite of this I believe this one has something extra in

it in it

# re: IoC and the Unity Application Block Once Again

Thursday, December 20, 2012 11:55 PM by Webber

Very nice post. I just stumbled upon your blog and wanted to say that I have truly enjoyed surfing around your

blog posts. In any case I'll be subscribing to your rss feed and I hope you write again very soon!

# re: IoC and the Unity Application Block Once Again

Monday, December 24, 2012 6:15 PM by Ruff

This is my first time I have visited your site. I found plenty of interesting

information in your blog. Out of the quite a lot of comments on your posts, I guess

I am not the merely one! keep up that the great work.

# re: IoC and the Unity Application Block Once Again

Tuesday, December 25, 2012 1:15 AM by Hostetler

Very man or woman speeches need to seat giving observe into couples.

Brand new sound method just before unnecessary people

should always be mindful of usually senior common rule out

of public speaking, which can be to be that the mini.

best man speaches

# re: IoC and the Unity Application Block Once Again

Tuesday, December 25, 2012 3:11 AM by Graf

i would love to use hydrogen fuel on my car, this fuel is actually

nonpolluting in spite of this is just not yet very available,.

# re: IoC and the Unity Application Block Once Again

Tuesday, December 25, 2012 11:03 PM by Bunker

foot massage have been very relaxing, i love to have a foot massage after a hard days work”

# re: IoC and the Unity Application Block Once Again

Saturday, December 29, 2012 10:32 AM by Schenk

hey read your post – Gulvafslibning Kurt Gulvmand in spite of this couldn’t get a hold of your contact form.

Is there a better method to contact you then through comments?

# re: IoC and the Unity Application Block Once Again

Sunday, December 30, 2012 12:23 AM by Horner

This is some great information. I expect additional facts something like this was distributed across that the web today.

# re: IoC and the Unity Application Block Once Again

Wednesday, January 2, 2013 7:28 AM by Pitts

He keeps both strands moving along at equal pace, Cage’s is more

engrossing; that the film paying sly hint to knowing so when it

utilises the concoction of Hit-Girl to drive that the film’s

final act on behalf of Cage’s plight.

# re: IoC and the Unity Application Block Once Again

Wednesday, January 9, 2013 3:27 AM by Mcneal

WOW just what I was searching for. Came here by searching for type body

# re: IoC and the Unity Application Block Once Again

Thursday, January 17, 2013 2:33 PM by Scully

The core of your writing whilst appearing agreeable initially, did not sit very

well with me personally after some time. Someplace throughout that the sentences you

really were able to make me a believer unfortunately merely for

a while. I on that the other hand have a query with your leaps in logic and you

might do well to fill in those breaks. In that the event

that you really can accomplish that, I could certainly be fascinated.

# re: IoC and the Unity Application Block Once Again

Sunday, February 3, 2013 8:56 AM by Cyr

You could definitely see your expertise

within the work you write. The arena hopes for even more

passionate writers such as you who are not afraid to mention how they believe.

Always go after your heart.

# re: IoC and the Unity Application Block Once Again

Monday, February 18, 2013 2:37 PM by Helton

I am genuinely thankful to the holder of this web page who has shared this wonderful piece of writing

at here.

# re: IoC and the Unity Application Block Once Again

Monday, February 18, 2013 2:40 PM by Snook

Heya i'm for the first time here. I found this board and I find It truly useful & it helped me out a lot. I am hoping to provide one thing again and help others such as you aided me.

# re: IoC and the Unity Application Block Once Again

Wednesday, February 20, 2013 1:51 AM by Stephen

I take pleasure in, cause I discovered just what I was looking for.

You have ended my 4 day long hunt! God Bless you man.

Have a nice day. Bye

# re: IoC and the Unity Application Block Once Again

Wednesday, February 20, 2013 2:07 AM by Page

This is a topic that's near to my heart... Many thanks! Exactly where are your contact details though?

# re: IoC and the Unity Application Block Once Again

Wednesday, February 20, 2013 2:08 AM by Page

This is a topic that's near to my heart... Many thanks! Exactly where are your contact details though?

# re: IoC and the Unity Application Block Once Again

Wednesday, February 20, 2013 4:11 AM by Money

My relatives always say that I am killing my time here at net, however I know I am getting

familiarity everyday by reading such good content.

# re: IoC and the Unity Application Block Once Again

Monday, March 25, 2013 1:45 PM by Christmas

Currently it seems like BlogEngine is the preferred blogging platform available right now.

(from what I've read) Is that what you're using

on your blog?

# re: IoC and the Unity Application Block Once Again

Monday, April 1, 2013 10:10 AM by Ridenour

Hi there, just became alert to your blog through Google,

and found that it is truly informative. I am going to watch out for brussels.

I will appreciate if you continue this in future.

Lots of people will be benefited from your writing.

Cheers!