.NET Core依赖注入实例何时处理?

Kei*_*ith 39 dependency-injection idisposable .net-core asp.net-core

ASP.NET Core使用扩展方法IServiceCollection来设置依赖注入,然后当需要类型时,它使用适当的方法来创建新实例:

  • AddTransient<T> - 添加每次请求时再次创建的类型.
  • AddScoped<T> - 添加为请求范围保留的类型.
  • AddSingleton<T> - 在第一次请求时添加一个类型并保持它.

我有类型的实现IDisposable,如果没有处理它们会导致问题 - 在Dispose实际调用的每个模式中?

有什么我需要添加(例如异常处理)以确保实例始终处置?

Tse*_*eng 41

解析的对象与其容器具有相同的生命周期/处置周期,除非您使用using语句或.Dispose()方法在代码中手动处理临时服务.

在ASP.NET Core中,您将获得一个作用域容器,该容器根据请求进行实例化,并在请求结束时处理.此时,由此容器创建的范围和瞬态依赖关系也将被处理(即如果它们实现IDisposable接口),您也可以在此处看到源代码.

public void Dispose()
{
    lock (ResolvedServices)
    {
        if (_disposeCalled)
        {
            return;
        }
        _disposeCalled = true;
        if (_transientDisposables != null)
        {
            foreach (var disposable in _transientDisposables)
            {
                disposable.Dispose();
            }

            _transientDisposables.Clear();
        }

        // PERF: We've enumerating the dictionary so that we don't allocate to enumerate.
        // .Values allocates a ValueCollection on the heap, enumerating the dictionary allocates
        // a struct enumerator
        foreach (var entry in ResolvedServices)
        {
            (entry.Value as IDisposable)?.Dispose();
        }

        ResolvedServices.Clear();
    }
}
Run Code Online (Sandbox Code Playgroud)

当父容器被处置时,单身人士会被处理,通常意味着当应用程序关闭时.

TL; DR:只要您在应用程序启动(使用app.ApplicationServices.GetService<T>())期间没有实例化范围/临时服务,并且您的服务正确实现了Disposable接口(如MSDN中指出的那样),您就不需要处理任何事情.

父容器在Configure(IApplicationBuilder app)方法之外是不可用的,除非你做一些时髦的东西以使它可以在外面访问(你不应该这样做).

当然,它鼓励尽快释放瞬态服务,特别是如果他们消耗了大量资源.

  • 无关,但我有点震惊地看到“lock”被用于公共可见的属性(本例中为“ResolvedServices”),我一直认为这违反了建议。 (2认同)