Skip to content

Owned<T> – Controlled Lifetime with Autofac

Last updated on March 28, 2019

In general, Autofac controls the lifetime of components. It automatically disposes off all the disposable components at the end of lifetime scope. However, that may mean a component is held onto for too long. Generally speaking, an owned dependency corresponds to some unit of work performed by the dependent component.

 

Releasing an Owned<T>

We use an owned dependency when we want to control the disposal of components on our own. The owner of an owned dependency controls the life time of that component. Therefore, the owner can release the component when it is no more required. Consequently, the unused component is not held for too long, waiting for the scope to end.

When we dispose a component, only that component is disposed and not its dependencies. However, when we release an owned component, all its dependencies along with the component are disposed. It is equally important to note, that shared dependencies (e.g., singletons) of the component will not be disposed.

 

The Magic behind Owned

Honestly speaking, there is no such magic. Internally, Autofac creates a lifetime scope in which IService is resolved, and when we call Dispose() on it, the lifetime scope is disposed. This is to say that, disposing of IService will also dispose of its dependencies unless those dependencies are shared (e.g., singletons).

public class Consumer
{
  Owned<IService> _service;
  public Consumer(Owned<IService> service) 
  { _service = service; }

  public void ConsumeService()
  {
      // _service is used for some task
      _service.Value.DoSomething();

      // _service is no longer needed here, so it is released
      _service.Dispose();
  }
}

 

The Catch

In the above example, if we register our service as InstancePerLifetimeScope() and resolve it as Owned<IService> then we may not get the same instance as being used elsewhere in the same lifetime scope. Please refer the below code (from Autofac documentation):

var builder = new ContainerBuilder();
builder.RegisterType<Consumer>().InstancePerLifetimeScope();
builder.RegisterType<IService>().InstancePerLifetimeScope();
var container = builder.Build();

using(var scope = container.BeginLifetimeScope())
{
  //Here we resolve a IService that is InstancePerLifetimeScope();
  var serviceOne = scope.Resolve<IService>();
  serviceOne.DoSomething();

  //This will be the same as serviceOne from above.
  var serviceTwo = scope.Resolve<IService>();
  serviceTwo.DoSomething();

  //The IService used in Consumer will NOT be the same as the others.
  var consumer = scope.Resolve<Consumer>();
  consumer.ConsumeService();
}

 

This is obvious because we don’t want one component to dispose the IService out from under everything else. However, if we want to control the disposal of a component all the time, it is recommended to register it that component as ExternallyOwned(), in which case, the container will never call Dispose() on it.

builder.RegisterType<SomeComponent>()
       .ExternallyOwned();

 

Published inDesign Patterns & Principles