views:

1034

answers:

3

Generally, I like to keep an application completely ignorant of the IoC container. However I have ran into problems where I needed to access it. To abstract away the pain I use a basic Singleton. Before you run for the hills or pull out the shotgun, let me go over my solution. Basically, the IoC singleton does absolutly nothing, it simply delegates to an internal interface that must be passed in. I've found this makes working with the Singleton less painful.

Below is the IoC wrapper:

public static class IoC
    {
        private static IDependencyResolver inner;

        public static void InitWith(IDependencyResolver container)
        {
            inner = container;
        }

        /// <exception cref="InvalidOperationException">Container has not been initialized.   Please supply an instance if IWindsorContainer.</exception>
        public static T Resolve<T>()
        {
            if ( inner == null)
                throw new InvalidOperationException("Container has not been initialized.  Please supply an instance if IWindsorContainer.");

            return inner.Resolve<T>();
        }

        public static T[] ResolveAll<T>()
        {
            return inner.ResolveAll<T>();
        }
    }

IDependencyResolver:

public interface IDependencyResolver
    {
        T Resolve<T>();
        T[] ResolveAll<T>();
    }

I've had great success so far with the few times I've used it (maybe once every few projects, I really prefer not having to use this at all) as I can inject anything I want: Castle, a Stub, fakes, etc.

Is this a slippery road? Am I going to run into potential issues down the road?

A: 

That's not really a singleton class. That's a static class with static members. And yes that seems a good approach.

I think JP Boodhoo even has a name for this pattern. The Static Gateway pattern.

chrissie1
+1  A: 

Just a note: Microsoft Patterns and Practices has created a common service locator (http://www.codeplex.com/CommonServiceLocator) that most of the major IoC containers will be implementing in the near future. You can begin to use it instead of your IDependencyResolver.

BTW: this is the common way to solve your problem and it works quite well.

Craig Wilson
+3  A: 

I've seen that even Ayende implements this pattern in the Rhino Commons code, but I'd advise against using it wherever possible. There's a reason Castle Windsor doesn't have this code by default. StructureMap does, but Jeremy Miller has been moving away from it. Ideally, you should regard the container itself with as much suspicion as any global variable.

However, as an alternative, you could always configure your container to resolve IDependencyResolver as a reference to your container. This may sound crazy, but it's significantly more flexible. Just remember the rule of thumb that an object should call "new" or perform processing, but not both. For "call new" replace with "resolve a reference".

Julian Birch