Disposal

https://autofac.readthedocs.io/en/latest/lifetime/disposal.html

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.

Autofac solves these problems using lifetime scopes as a way of disposing of all of the components created during a unit of work.

using (var scope = container.BeginLifetimeScope())
{
  scope.Resolve<DisposableComponent>().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.

var builder = new ContainerBuilder();
builder.RegisterType<SomeDisposableComponent>();
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 behaviour 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:

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<MyComponent>():

    // 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 throw an exception, because it does not know how to dispose of your component.

Specified Disposal

If your component doesn’t implement IDisposable but still requires some cleanup at the end of a lifetime scope, you can use the OnRelease lifetime event.

var builder = new ContainerBuilder();
builder.RegisterType<SomeComponent>()
       .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().

原文地址:https://www.cnblogs.com/chucklu/p/12578951.html