Resources obtained within the work unit (database connections, transactions, authentication sessions, file handles, etc.) should be destroyed upon completion of the work. NET provides a IDisposable interface to help destroy this more defined concept.
Some IOC containers need to be explicitly told to destroy specific instances through methods like ReleaseInstance (). This makes it difficult to guarantee the use of correct destruction semantics. Switching from a non-destroyed part to a removable part may mean modifying the client code. Client code may ignore destruction when it uses shared instances, but it is almost certainly not clear when switching to a nonshared instance.
AUTOFAC solves these problems by using the lifecycle as a way to destroy all the components created in the unit of work.
using (var scope = container. Beginlifetimescope ())
{
scope. Resolve<disposablecomponent> (). DoSomething ();
In the case where the scope itself is destroyed, at the end of the ' using ' declaration, the destroyed scope component is placed here.
}
The scope of the lifecycle is created at the beginning of the work unit, and when the work unit completes, the nested container can destroy all instances beyond the scope. Registering Components
AUTOFAC can automatically destroy some components, but you can also manually specify the destruction mechanism.
The component must be registered as a variant of instanceperdependency () (default) or Instanceperlifetimescope () (for example, Instancepermatchinglifetimescope () or Instanceperrequest ()).
If you have singleton components (registered as singleinstance ()), they will survive the entire lifecycle of the container. Because the life of the container is usually the lifecycle of the application, this means that the component will not be destroyed until the end of the application. Automatic Destruction
To take advantage of automatic deterministic destruction, your component must implement IDisposable. You can then register the component as needed and call the Dispose () method on the component at the end of each lifecycle scope that the component resolves.
var builder = new Containerbuilder ();
Builder. Registertype<somedisposablecomponent> ();
var container = Builder. Build ();
Creates nested lifecycle scopes, resolves components, and destroys scopes.
//Your component will be destroyed along with the scope.
Specify Destroy
If your component does not implement IDisposable, but you still need to do some cleanup at the end of the lifecycle, you can use Onrelease lifecycle events.
var builder = new Containerbuilder ();
Builder. Registertype<somecomponent> ()
. Onrelease (instance => instance. CleanUp ());
var container = Builder. Build ();
Creates nested lifecycle scopes, resolves components, and destroys scopes. The "CleanUp ()" Method of the component is invoked when the scope is processed.
Note that onrelease () overrides the default processing for IDisposable.Dispose (). If your components are implemented IDisposable and need some other cleanup methods, you need to manually call Dispose () in Onrelease (), or you will need to update your class to invoke the cleanup method from Dispose (). Disable Destroy
The component is owned by the container by default and destroyed by the container at the appropriate time. To disable this feature, register your component as having external ownership:
Builder. Registertype<somecomponent> (). Externallyowned ();
The container will never call Dispose () on objects registered with external ownership. It is up to you to handle the components that are registered in this manner.
Another way to disable destruction is to use implicit relational owned<t> and owning instances. In this case, instead of placing the dependency T in the consumer code, it relies on the owned<t>. Your consumer code will be processed.
public class Consumer
{
private owned<disposablecomponent> _service;
Public Consumer (owned<disposablecomponent> service)
{
_service = service;
}
The public void DoWork ()
{
//_service is used for a task
_service. Value.dosomething ();
Here _service is no longer needed, so it is released
_service. Dispose ();
}
}
You can read more about owned<t> in the instance topics that you have. resolving components from life cycle scope
The lifecycle scope is created by calling Beginlifetimescope (). The simplest method is in the using block. Use the lifecycle scope to resolve the component and then destroy the scope when the work unit completes.
using (var lifetime = container. Beginlifetimescope ())
{
var component = lifetime. Resolve<somecomponent> ();
Component and any of its available destroy dependencies will be destroyed when the using block completes
Note that when you use the AUTOFAC Integration Library, the standard work cell lifecycle scope is automatically created and destroyed. For example, in AUTOFAC's asp.net MVC integration, a Web request starts with a lifecycle scope created for you, and all components are parsed from here. At the end of a network request, the scope is automatically destroyed-you do not need to create additional scopes. If you are using one of the integrated libraries, you should know that the scope that is automatically created is available. child scopes are not automatically disposed
Although the lifecycle scope itself implements IDisposable, the life cycle scope you create does not automatically destroy. If you create a lifecycle scope, you will be responsible for calling Dispose () to clean it up and trigger automatic processing of the component. You can easily do this with a using statement, but if you create a scope without using it, do not forget to destroy the scope when it is finished.
It is important to differentiate between the scope you create and the scope that the integration library creates for you. You do not have to worry about managing the integration scope (such as ASP.net request scope)-These will be done for you. However, if you create your own scope manually, you will be responsible for cleaning it up. Advanced Hierarchy
The simplest and most desirable resource management scenarios demonstrated above are two-tiered: there is a separate ' root ' container in which each unit of work creates a lifecycle scope. You can create a more complex hierarchy of containers and components, but use the lifecycle scope of the tag.