Search code examples
c#autofac

Autofac RegisterAssemblyTypes and RegisterType instanciates same implementation twice when SingleInstance Specified


Say I have generic interface:

interface ITestGeneric<T>
{
    void Test(T t);
}

and 2 implemetations:

class TestImpl1 : ITestGeneric<string>
{
    private readonly string key;

    public TestImpl1(string key=null)
    {
        this.key = key;
    }
    public void Test(string t)
    {
        Console.WriteLine(key);
    }
}
 class TestImp2 : ITestGeneric<string>
{
    public void Test(string t)
    {
        Console.WriteLine(2);

    }
}

and registering services as follows:

var builder = new ContainerBuilder();
        builder.RegisterAssemblyTypes(typeof(Program).GetTypeInfo().Assembly).AsClosedTypesOf(typeof(ITestGeneric<>));
        builder.RegisterType<TestImpl1>().AsImplementedInterfaces().SingleInstance().WithParameter(new TypedParameter(typeof(string),"value1"));
        

Here I'm providing explicit parameter for implementation TestImpl1 and making it singleton. Problem is, when I resolve service with IEnumerable<ITestGeneric>, I get multiple activations of TestImpl1 with no parameter provided, although expected behavior should be registering it singleton as provided explicitly.

 var c= builder.Build();
 var kk = c.Resolve<ITestGeneric<string>>();
 var r = c.Resolve<IEnumerable<ITestGeneric<string>>>();
 r = c.Resolve<IEnumerable<ITestGeneric<string>>>();
 r = c.Resolve<IEnumerable<ITestGeneric<string>>>();
//creates multiple instances on TestImpl1

How can I provide for that single implementation TestImpl1 custom behavior like singleton and explicit parameter, but also register all assembly generic types?

P.S. making RegisterAssemblyTypes singleton, leaves me we 2 instances of TestImpl1, one of which has no provided parameter in constructor.


Solution

  • You can filter RegisterAssemblyTypes with Where:

    builder.RegisterAssemblyTypes(typeof(AutofacTests).GetTypeInfo().Assembly)
        .Where(type => type != typeof(TestImpl1))
        .AsClosedTypesOf(typeof(ITestGeneric<>));
    

    Or Except:

    builder.RegisterAssemblyTypes(typeof(AutofacTests).GetTypeInfo().Assembly)
        .Except<TestImpl1>()
        .AsClosedTypesOf(typeof(ITestGeneric<>));