Search code examples
c#inversion-of-controllight-inject

How to override a type already registered in LightInject using a new instance passed to the constructor?


In repository I keep some instances which live throughout the lifetime of my application but sometimes I need an immediate replacement for such instance with another instance and LightInject even if passing the new instance to the container.GetInstance constructor override.

Here is a snippet showing the problem:

    internal class ClassA
    {
        public string Name { get; private set; }

        public ClassA(string name)
        {
            Name = name;
        }

        public override string ToString()
        {
            return Name;
        }
    }

    internal class ClassB
    {
        public ClassA A { get; private set; }

        public ClassB(ClassA a)
        {
            A = a;
        }

        public override string ToString()
        {
            return string.Format("I contain {0}", A);
        }
    }

    private void TestContainer()
    {
        var container = new LightInject.ServiceContainer();
        var a1 = new ClassA("A instance 1");
        container.Register(x => a1);
        container.Register<ClassB>();

        var a2 = new ClassA("A instance 2");
        var bwitha1 = container.GetInstance<ClassB>();
        if(bwitha1.A != a1)
        {
            throw new InvalidOperationException("This will not happen");
        }
        var bwitha2 = container.GetInstance<ClassA, ClassB>(a2);
        if(bwitha2.A != a2)
        {
            throw new InvalidOperationException("Something went wrong here");
        }
    }

Why LightInject previously registered instance takes precedence if I give explicit instance in GetInstance call? How to get around the issue and construct the object with an alternative instance of one of the arguments?


Solution

  • In the current version of LightInject you need to provide a factory if you want to use runtime arguments.

    The following workaround might work for you.

    using LightInject;
    
    class Program
    {
        static void Main(string[] args)
        {
            var container = new ServiceContainer();
            container.Register<Bar>();
            container.Register<Foo>();
            container.Register<Bar, Foo>((factory, bar) => new Foo(bar), "FooWithRuntimeArgument");            
            var instance = container.GetInstance<Foo>();            
            var instanceWithRuntimeArgument = container.GetInstance<Bar, Foo>(new Bar(), "FooWithRuntimeArgument");
        }
    }
    
    public class Foo
    {                
        public Foo(Bar bar) {}        
    }
    
    public class Bar {}