【问题标题】:When are .NET Core dependency injected instances disposed?.NET Core 依赖注入实例何时处置?
【发布时间】:2017-04-12 03:59:38
【问题描述】:

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

  • AddTransient<T> - 添加一个每次请求时都会重新创建的类型。
  • AddScoped<T> - 添加在请求范围内保留的类型。
  • AddSingleton<T> - 在第一次请求时添加类型并保留它。

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

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

【问题讨论】:

    标签: dependency-injection asp.net-core .net-core idisposable


    【解决方案1】:

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

    在 ASP.NET Core 中,您会获得一个作用域容器,该容器会根据请求进行实例化,并在请求结束时释放。此时,这个容器创建的作用域和临时依赖也将被释放(如果它们实现了IDisposable 接口),你也可以在源代码here 中看到。

    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();
        }
    }
    

    当父容器被释放时,单例被释放,通常意味着当应用程序关闭时。

    TL;DR:只要您在应用程序启动期间不实例化作用域/瞬态服务(使用 app.ApplicationServices.GetService<T>())并且您的服务正确实现 Disposable 接口(如 pointed in MSDN),就可以没有什么你需要照顾的。

    父容器在Configure(IApplicationBuilder app) 方法之外不可用,除非你做一些时髦的事情让它可以在外面访问(无论如何你都不应该这样做)。

    当然,鼓励尽快释放临时服务,尤其是在它们消耗大量资源的情况下。

    【讨论】:

    • 不相关,但看到lock 被用于公开可见的财产(在本例中为ResolvedServices),我感到有点震惊,我一直认为这违反了建议。跨度>
    • @StevenRands: ResolvedServices 是内部事务
    • @Tseng 是的,它是内部的,但从技术上讲,它对同一程序集中的其他类型是公开的。
    猜你喜欢
    • 2022-01-01
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 2021-02-02
    • 1970-01-01
    • 2018-04-05
    相关资源
    最近更新 更多