Search code examples
c#autofaclifetime-scoping

can Autofac do different instance scoping per interface?


Suppose I have this line in my bootstrap code:

builder.RegisterType<MyType>().As<IMyType>().As<IMyTypeBase>().ExternallyOwned();

I want it such that whenever I use container.Resolve<IMyType>() I get a new instance of MyType. However, if I use container.Resolve<IEnumerable<IMyTypeBase>>(), I don't want new instances. I want all of the instances that have already been created. Is this possible with Autofac?


Solution

  • Your requirement seems conflicting and you should reconsider your strategy. The behavior you want can lead to very surprising results and determines on the order in which types are resolved or even in which order the constructor parameters are ordered.

    Take a look at the following example for instance:

    var instance1 = container.Resolve<IMyType>();
    var instance2 = container.Resolve<IEnumerable<IMyTypeBase>>().First();
    
    Assert.AreSame(instance1, instance2);
    

    Here we first resolve the IMyType and later resolve the collection of IMyTypeBase instances and you expect the collection to return the same instance. But what if we turn this around?

    var instance2 = container.Resolve<IEnumerable<IMyTypeBase>>().First();
    var instance1 = container.Resolve<IMyType>();
    

    Do you still expect both instances to be the same? When Resolve<IEnumerable<IMyTypeBase>>() is called, there is no MyType instance yet, so it will be created. But your requirement is to always create a new instance when resolving IMyType, so in this case two instances will be created.

    To make this worse, take a look at the following two constructors:

    public SomeService(IMyType type, IEnumerable<IMyTypeBase> types) { ... }
    
    public OtherService(IEnumerable<IMyTypeBase> types, IMyType type) { ... }
    

    The simple fact that OtherService defines the IEnumerable<IMyTypeBase> parameter first, will cause two MyType instances to be created. And you might be able to see this in this particular case, but since object graphs can become very deep, it becomes almost impossible to guess the number of instances of MyType to be created.