|
|
Introduction
Resources obtained within a unit of work - database connections, transactions, authenticated sessions, file handles etc. - should be disposed of when that work is complete.
Traditional IoC containers need to be told explicitly to dispose of a particular instance, through a method like 'ReleaseInstance().' This makes it very difficult to guarantee that the correct disposal semantics are adhered to:
- Switching implementations from a non-disposable to a disposable component can mean modifying client code
- Client code that may have ignored disposal when using singleton instances will almost certainly fail to clean up when switched to factory instances
Autofac solves these problems using nested containers as a way of disposing of all of the components created during a unit of work.
A nested container is created when a unit of work begins, and when that unit of work is complete the nested container can dispose all of the instances within it that are out of scope.
Registering Components
To take advantage of deterministic disposal, a component must:
- Be registered with Factory or Container scope
- Implement IDisposable
var builder = new ContainerBuilder(); builder.Register<SomeComponent>().FactoryScoped(); var container = builder.Build();
Disposing of a nested container won't dispose of Singleton components (these will be disposed of when the root container is disposed.)
Using the Nested Container
Nested containers are created by calling Container.CreateInnerContainer(). The simplest way of using a nested container is in a using block:
using (var inner = container.CreateInnerContainer())
{
var component = inner.Resolve<SomeComponent>();
// component, and any of its disposable dependencies, will
// be disposed of when the using block completes
}This pattern is fine to use whenever it seems appropriate, however, in a web application the inner container will generally be created when the request processing begins, and will be disposed of when processing ends. Use the provided HTTP module for this.
Disabling Disposal
Components are owned by the container by default, and will be disposed along with it. To disable this, register a component as having external ownership:
builder.Register<SomeComponent>().ExternallyOwned();
The container will never call Dispose() on an object registered with external ownership.
Advanced Hierarchies
The simplest and most advisable resource management scenario, demonstrated above, is two-tiered: there is a single 'root' container and a child container is created from this for each unit of work. It is possible to create more complex hierarchies of containers and components, however, using tags.
Sign in to add a comment
