【问题标题】:Autofac: Dispose off object instance and its dependencies with just the resolved instance?Autofac:仅使用已解析的实例处理对象实例及其依赖项?
【发布时间】:2020-04-13 16:49:00
【问题描述】:

假设我有一个对象的实例,由 Autofac 解析,如下所示:

ILifetimeScope scope = rootContainer....
var myService = scope.Resolve(myServiceType);

现在我只有myService。是否有任何 Autofac API 接受我的变量 myService 并将其处理掉(连同 Autofac 解析的所有依赖项)?

例如

// later at some point, something like this
rootContainer.DisposeOff(myService) // <-- this should dispose the lifetime scope of myService, i.e. dispose myService, along with its other dependencies.

注意几点:

  1. 我当然不能自己做myService.Dispose(),因为这不会释放 Autofac 注入的子依赖项(因为 Autofac 控制着它们的生命周期)。
  2. 我身边只有myService。这是我正在处理的图书馆的特殊性质。我当然可以自己存储scope 变量并对其进行管理。那将是我最后的手段。只是想知道 Autofac 是否内置了一些东西。

【问题讨论】:

  • Autofac 有OnRelease 事件,它对您的情况会有所帮助,请查看docs
  • 可以修改注册服务的实现吗?
  • @Kazar 是的,我可以。
  • @PavelAnikhouski onrelease 事件略有不同。我没有什么可以清理自己的。当我准备好时,我只希望 autofac 提高版本。

标签: c# dependency-injection autofac lifetime-scoping


【解决方案1】:

Autofac 没有内置方法来处理来自某些根服务的依赖树;它只能处理在生命周期范围内解决的所有内容。

您需要将示波器存储在某个地方,以便以后处理。如果您无法传递除服务之外的任何内容,并且您的范围仅包含服务的依赖项,那么您可以想象在您的服务构造函数中注入 ILifetimeScope,以便服务可以持有对范围的引用。

然后,在服务的Dispose 方法中处理注入的作用域本身。为了防止您的服务在您这样做时也被 Autofac 处理,您应该将其注册为ExternallyOwned

containerBuilder.RegisterType<MyService>().ExternallyOwned();

我不喜欢它,但是如果您无法跟踪服务之外的范围,我不确定其他方式。

class MyService : IDisposable
{
   private ILifetimeScope _scope;
   public MyService(ILifetimeScope scope)
   { 
      _scope = scope;
   }

   public void Dispose()
   {
     if(_scope is object)
     { 
        var localScope = _scope;
        _scope = null;
        localScope.Dispose();
     }
   }
}

【讨论】:

  • 很公平。我不喜欢第二种选择。我将使用存储范围方法。
【解决方案2】:

服务与解析它的范围相关联。当您解析范围时,Autofac 将负责处理需要处理的服务。

您应该创建生命周期范围并处理它们,而不是直接从容器中解析

using(var scope = rootContainer.BeginLifetimeScope())
{
    IService service = scope.Resolve<IService>(); 

    // do whatever you want 
} // service will be disposed here, at the end of the lifetime scope 

您也可以使用Owned&lt;T&gt;,它可以作为一个非常轻便的示波器,并且可以轻松解决。

using(Owned<IService> ownedService = scope.Resolve<Owned<Iservice>>())
{
    IService service = ownedService.Value; 
    // do whatever you want
}

当然,Autofac 只会处理所需的资源。如果服务注册为SingleInstance,它不会在需要它的生命周期结束时处理它。

【讨论】:

  • Cyril,我不能附在using 中,因为这会立即处理 IService。就我而言,它的寿命会更长。当 IService 实例完成时,我从外部库中收到一个事件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-29
  • 2023-03-27
  • 1970-01-01
相关资源
最近更新 更多