Search code examples
c#dependency-injectioninversion-of-controlunity-container

Unity Extending Dependency Injection Containers


I'm working on a project which currently uses the Service Locator Anti-Pattern all over the code. I'm starting the process to slowly convert everything to using dependency injection, however because of the sheer size of the project I'd like to do this over the course of time.

I'm have a custom factory with 100's of dependencies registered with custom implementations. So I'd like to just wrap my container with unity, if my current container doesn't have the implementation then fall back to use unitys.

I've written this class to wrap IUnityContainer

public class GlobalFactoryUnityWrapper : IUnityContainer
{
    IUnityContainer _unityContainer = new UnityContainer();
    IUnityContainer _parent;

    public GlobalFactoryUnityWrapper(IUnityContainer parent = null)
    {
        this._parent = parent ?? this._unityContainer.Parent;
    }

    public IUnityContainer Parent => this._parent;

    //... Other IUnityContainer members

    public object Resolve(Type type, string name, params ResolverOverride[] resolverOverrides)
    {
        if(GlobalContext.InstanceFactory.CanGetInstance(type))
        {
            return GlobalContext.InstanceFactory.GetInstance(type);
        }

        return this._unityContainer.Resolve(type, name, resolverOverrides);
    }
}

I have most of the dependencies register for my controller there, However the controllers themselves are not, So it falls back to use unity's container.

Edit I think I'm using the wrong thing, I should be using a strategy. my main goal is if the container doesn't contain an implementation, Fall back to use a what's registered in the old container


Solution

  • I needed to create a fallback strategy, this probably isn't the most optimal code but it's working for now

    public class FactoryFallbackExtension : UnityContainerExtension
    {
        public FactoryFallbackExtension()
        {
        }
    
        protected override void Initialize()
        {
            var strategy = new FallBackStrategy(Context);
            Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
        }
    }
    public class FallBackStrategy : BuilderStrategy
    {
        private ExtensionContext baseContext;
    
        public FallBackStrategy(ExtensionContext baseContext)
        {
            this.baseContext = baseContext;
        }
    
        public override void PreBuildUp(IBuilderContext context)
        {
            var key = context.OriginalBuildKey;
            if (key.Type.IsInterface)
            {
                if(GlobalContext.InstanceFactory.CanGetInstance(key.Type))
                    context.Existing = GlobalContext.InstanceFactory.GetInstance(key.Type);    
            }
        }
    }
    

    Then When I configure my container I can just add the Container extension like so:

    public static void Configure()
    {
        var container = new UnityContainer();
        RegisterDepedencies(container);
        container.AddExtension(new FactoryFallbackExtension());
        GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
        SetControllerFactory(container);
    }