======== Disposal ======== Resources obtained within a unit of work - database connections, transactions, authenticated sessions, file handles etc. - should be disposed of when that work is complete. .NET provides the ``IDisposable`` interface to aid in this more deterministic notion of disposal. Some 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 used. * Switching implementations from a non-disposable to a disposable component can mean modifying client code. * Client code that may have ignored disposal when using shared instances will almost certainly fail to clean up when switched to non-shared instances. :doc:`Autofac solves these problems using lifetime scopes ` as a way of disposing of all of the components created during a unit of work. .. sourcecode:: csharp using (var scope = container.BeginLifetimeScope()) { scope.Resolve().DoSomething(); // Components for scope disposed here, at the // end of the 'using' statement when the scope // itself is disposed. } A lifetime scope 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 ====================== Autofac can automatically dispose of some components, but you have the ability to manually specify a disposal mechanism, too. Components must be registered as ``InstancePerDependency()`` (the default) or some variation of ``InstancePerLifetimeScope()`` (e.g., ``InstancePerMatchingLifetimeScope()`` or ``InstancePerRequest()``). If you have singleton components (registered as ``SingleInstance()``) **they will live for the life of the container**. Since container lifetimes are usually the application lifetime, it means the component won't be disposed until the end of the application. Automatic Disposal ------------------ To take advantage of automatic deterministic disposal, your component must implement ``IDisposable``. You can then register your component as needed and at the end of each lifetime scope in which the component is resolved, the ``Dispose()`` method on the component will be called. .. sourcecode:: csharp var builder = new ContainerBuilder(); builder.RegisterType(); var container = builder.Build(); // Create nested lifetime scopes, resolve // the component, and dispose of the scopes. // Your component will be disposed with the scope. Asynchronous Disposal Support ----------------------------- If your components' disposal behavior requires some I/O activity, such as flushing a buffer to a file, or sending a packet over the network to close a connection, then you may want to consider implementing the new .NET `IAsyncDisposable `_ interface. In Autofac 5.0, support was added for the ``IAsyncDisposable`` interface, so lifetime scopes can now be disposed of asynchronously: .. code-block:: csharp class MyComponent : IDisposable, IAsyncDisposable { INetworkResource myResource; public void Dispose() { myResource.Close(); } public async ValueTask DisposeAsync() { await myResource.CloseAsync(); } } // ... await using (var scope = container.BeginLifetimeScope()) { var service = scope.Resolve(): // DisposeAsync will be called on MyComponent // when the using block exits. } When a lifetime scope is disposed of asynchronously, any registered components that implement ``IAsyncDisposable`` in addition to ``IDisposable`` will have their ``DisposeAsync()`` method invoked, **instead** of the ``Dispose()`` method. If a component only implements the synchronous ``Dispose()`` method, then it will still be invoked when the lifetime scope is disposed asynchronously. When using Autofac with the ASP.NET Core Integration, all per-request lifetime scopes are disposed of asynchronously. .. important:: While you do not *have* to implement ``IDisposable`` if you implement ``IAsyncDisposable``, we strongly recommend you do so. If your component only implements ``IAsyncDisposable``, but someone disposes of the scope synchronously, then Autofac will be forced to use a sync-over-async blocking dispose, and will raise a :doc:`diagnostic warning <../troubleshooting/diagnostics>`: AUTOFAC: A synchronous Dispose has been attempted, but the tracked object of type 'AsyncComponent' only implements IAsyncDisposable. This will result in an inefficient blocking dispose. Consider either implementing IDisposable on 'AsyncComponent' or disposing of the scope/container with DisposeAsync. Specified Disposal ------------------ If your component doesn't implement ``IDisposable`` but still requires some cleanup at the end of a lifetime scope, you can use :doc:`the OnRelease lifetime event `. .. sourcecode:: csharp var builder = new ContainerBuilder(); builder.RegisterType() .OnRelease(instance => instance.CleanUp()); var container = builder.Build(); // Create nested lifetime scopes, resolve // the component, and dispose of the scopes. // Your component's "CleanUp()" method will be // called when the scope is disposed. Note that ``OnRelease()`` overrides the default handling of ``IDisposable.Dispose()``. If your component both implements ``IDisposable`` *and* requires some other cleanup method, you will either need to manually call ``Dispose()`` in ``OnRelease()`` or you will need to update your class so the cleanup method gets called from inside ``Dispose()``. Disabling Disposal ------------------ Components are owned by the container by default and will be disposed by it when appropriate. To disable this, register a component as having external ownership: .. sourcecode:: csharp builder.RegisterType().ExternallyOwned(); The container will never call ``Dispose()`` or ``DisposeAsync()`` on an object registered with external ownership. It is up to you to dispose of components registered in this fashion. Another alternative for disabling disposal is to use the :doc:`implicit relationship <../resolve/relationships>` ``Owned`` and :doc:`owned instances <../advanced/owned-instances>`. In this case, rather than putting a dependency ``T`` in your consuming code, you put a dependency on ``Owned``. Your consuming code will then be responsible for disposal. .. sourcecode:: csharp public class Consumer { private Owned _service; public Consumer(Owned service) { _service = service; } public void DoWork() { // _service is used for some task _service.Value.DoSomething(); // Here _service is no longer needed, so // it is released _service.Dispose(); } } You can read more about ``Owned`` :doc:`in the owned instances topic <../advanced/owned-instances>`. Resolve Components from Lifetime Scopes ======================================= Lifetime scopes are created by calling ``BeginLifetimeScope()``. The simplest way is in a ``using`` block. Use the lifetime scopes to resolve your components and then dispose of the scope when the unit of work is complete. .. sourcecode:: csharp using (var lifetime = container.BeginLifetimeScope()) { var component = lifetime.Resolve(); // component, and any of its disposable dependencies, will // be disposed of when the using block completes } Note that with :doc:`Autofac integration libraries <../integration/index>` standard unit-of-work lifetime scopes will be created and disposed for you automatically. For example, in Autofac's :doc:`ASP.NET MVC integration <../integration/mvc>`, a lifetime scope will be created for you at the beginning of a web request and all components will generally be resolved from there. At the end of the web request, the scope will automatically be disposed - no additional scope creation is required on your part. If you are using :doc:`one of the integration libraries <../integration/index>`, you should be aware of what automatically-created scopes are available for you. You can :doc:`read more about creating lifetime scopes here `. Child Scopes are NOT Automatically Disposed =========================================== While lifetime scopes themselves implement ``IDisposable``, the lifetime scopes that you create are **not automatically disposed for you.** If you create a lifetime scope, you are responsible for calling ``Dispose()`` on it to clean it up and trigger the automatic disposal of components. This is done easily with a ``using`` statement, but if you create a scope without a ``using``, don't forget to dispose of it when you're done with it. It's important to distinguish between scopes **you create** and scopes the **integration libraries create for you**. You don't have to worry about managing integration scopes (like the ASP.NET request scope) - those will be done for you. However, if you manually create your own scope, you will be responsible for cleaning it up. Provided Instances ================== If you provide :doc:`an instance registration <../register/registration>` to Autofac, Autofac will assume ownership of that instance and will handle its disposal. .. sourcecode:: csharp // If you do this, Autofac will dispose of the StringWriter // instance when the container is disposed. var output = new StringWriter(); builder.RegisterInstance(output) .As(); If you want to take control of the disposal of the instance yourself, you need to register the instance as ``ExternallyOwned()``. .. sourcecode:: csharp // Using ExternallyOwned means you will be responsible for // disposing the StringWriter instead of Autofac. var output = new StringWriter(); builder.RegisterInstance(output) .As() .ExternallyOwned(); Advanced Hierarchies ==================== The simplest and most advisable resource management scenario, demonstrated above, is two-tiered: there is a single 'root' container and a lifetime scope is created from this for each unit of work. It is possible to create more complex hierarchies of containers and components, however, using :doc:`tagged lifetime scopes `.