Introduction
In general, Autofac controls the lifetime of components. It automatically disposes of all the disposable components at the end of lifetime scope. However, that may mean a component is held on to 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 lifetime of that component. Therefore, the owner can release the component when it is no longer required. Consequently, the unused component is not held for too long, waiting for the scope to end.
When we dispose of a component, only that component is disposed of and not its dependencies. However, when we release an owned component, all its dependencies along with the component are disposed of. It is equally important to note, that shared dependencies (e.g., singletons) of the component will not be disposed of.
- public class Consumer
- {
- Owned<IService> _service;
-
- public Consumer(Owned<IService> service)
- { _service = service; }
-
- public void ConsumeService()
- {
-
- _service.Value.DoSomething();
-
-
- _service.Dispose();
- }
- }
In the code above, Autofac internally 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).
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 to 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())
- {
-
- var serviceOne = scope.Resolve<IService>();
- serviceOne.DoSomething();
-
-
- var serviceTwo = scope.Resolve<IService>();
- serviceTwo.DoSomething();
-
-
- var consumer = scope.Resolve<IService>();
- consumer.ConsumeService();
- }
This is obvious because we don’t want one component to dispose of 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 that component as ExternallyOwned(), in which case, the container will never call Dispose() on it.
Related Articles