Ninject 中的 .NET Core DI 范围生命周期

Posted

技术标签:

【中文标题】Ninject 中的 .NET Core DI 范围生命周期【英文标题】:.NET Core DI scope lifetime in Ninject 【发布时间】:2018-12-12 07:20:37 【问题描述】:

编辑:由于许多用户错误地将其视为 ASP.NET 特定问题。请注意,我的应用程序不是 Web 应用程序,并且我没有使用 ASP.NET 应用程序(我正在使用它的功能,它在 .NET Core 中也可用)。


最近,在 Ninject DI 中配置 Entity Framework DbContext 生命周期时,我一直在研究 .NET Core 依赖注入,因为它已经具有注册 DbContext 的功能,可以在 here 找到。默认上下文生命周期为ServiceLifetime.Scoped

在代码预览中,我们可以读到在 ASP.NET 应用程序中,“作用域”意味着:

范围是围绕每个服务器请求创建的

namespace Microsoft.Extensions.DependencyInjection

    //
    // Summary:
    //     Specifies the lifetime of a service in an Microsoft.Extensions.DependencyInjection.IServiceCollection.
    public enum ServiceLifetime
    
        //
        // Summary:
        //     Specifies that a single instance of the service will be created.
        Singleton = 0,
        //
        // Summary:
        //     Specifies that a new instance of the service will be created for each scope.
        //
        // Remarks:
        //     In ASP.NET Core applications a scope is created around each server request.
        Scoped = 1,
        //
        // Summary:
        //     Specifies that a new instance of the service will be created every time it is
        //     requested.
        Transient = 2
    

我正在尝试在 Ninject DI 中实现类似的功能,但在谈到 .NET Core 应用程序(这不是 Web应用程序!)。

Ninject 有 InRequestScope 方法,但它仅适用于 Web 应用程序,因此它与 .NET Core DI ServiceLifetime.Scoped 设置确实不同。

也许我必须创建某种 custom scope in Ninject,但我仍然无法说明如何实现与 .NET Core DI 中完全相同的作用域行为。为此,我需要了解作用域生命周期在 .NET Core DI 中的 .NET Core 应用程序上下文中是如何工作的。我的猜测是,一旦应用程序退出,就会创建一个 DbContext 实例并被释放。

因此我的问题

.NET Core DI scope 生命周期设置如何工作?它的生命周期是什么? 是否可以在 Ninject DI 中实现类似的行为?

【问题讨论】:

What is the difference between services.AddTransient, service.AddScope and service.AddSingleton methods in Asp.Net Core?的可能重复 @tura08 请再次阅读我的问题。 This repository 包含如何使用作用域将 Ninject 集成到 ASP.NET Core 中的示例。 @Steven 对不起。我清楚地说,至少两次这不是针对 Web 应用程序的,这是关于为 .NET Core 应用程序移植 Ninject 的InRequestScope,就像 .NET Core DI 正在做的那样。我已经编辑了这个问题,所以现在会更清楚:) 嗨,Rusco,该存储库仍然为您提供了一些有关如何执行此操作的线索。 【参考方案1】:

.NET Core DI 范围生命周期设置如何工作以及它是什么 生命周期?

.Net 核心在内部使用名为 ServiceScope 的类。当调用新请求(例如 Web 请求)时,会创建新实例,并包含新的服务提供者。在请求期间,此服务提供者用于依赖关系解析。请求完成后,作用域和它的服务提供者及其解析的服务都被释放。

  internal class ServiceScope : IServiceScope, IDisposable
  
    private readonly Microsoft.Extensions.DependencyInjection.ServiceProvider _scopedProvider;

    public ServiceScope(Microsoft.Extensions.DependencyInjection.ServiceProvider scopedProvider)
    
      this._scopedProvider = scopedProvider;
    

    public IServiceProvider ServiceProvider
    
      get
      
        return (IServiceProvider) this._scopedProvider;
      
    

    public void Dispose()
    
      this._scopedProvider.Dispose();
    
  

是否有可能在 Ninject DI 中实现类似的行为?

正如您已经注意到的那样,实现自定义范围是可行的。您可以在另一个答案中查看如何执行此操作:

Ninject - In what scope DbContext should get binded when RequestScope is meaningless?

编辑:

.NET Core DI 的原理与任何其他 IOC 容器相同。它通过 DI 为您的对象(MVC 控制器等)提供依赖关系并控制其生命周期。

如果为 DbContext 指定单例生命周期,则只有一个是 创建,由 DI 在请求时提供并保存在内存中 整个应用程序/容器的生命周期。 如果您指定瞬态,您将获得新的 始终请求一个 DbContext。 如果指定范围, DbContext 的生命周期绑定到一些一次性范围,该范围是在一些逻辑请求的开始时创建的(在 asp 的情况下为 http 请求)。当 DbContext 是 DI 第一次请求,创建一个新的,保存在内存中,你在 后续 DI 请求,直到范围被释放(在 asp 的情况下,http 请求结束)和 DbContext 它。

您可以找到与 TransactionScope 类似的相似之处。在这里,同一个 TransactionScope 中的所有 sqlCommands 都被登记到同一个 sql 事务中,但作用域被释放/提交。

【讨论】:

其他答案中给出的解决方案仍然是不同的实现。我可以在没有 Ninject 的情况下使用 using 创建 DbContext。 .NET Core DI 之间的主要区别在于您不必使用using 语句来传递有效的 DbContext 实例。您只需将其注册为提供程序,它就会以某种方式工作。 @Rusco。你不使用 using 的原因是因为 asp.net core 它为你做到了! @Rusco 所以这意味着要么让你在框架上创建和处置范围,要么你必须自己控制范围的生命周期(因为你不是在开发 asp 应用程序)。反正总会有这么一段代码。 Ninject 例子完全一样。 我明白了......但我想知道它是如何完成的?我的意思是,.NET Core DI 如何能够不强迫我们在每个 dbcontext 调用上创建一个新的上下文?幕后魔术是如何运作的,他们是如何做到的?我们能否使用 Ninject 在 .NET Core 应用程序中实现类似的功能?喜欢在我们应用的更广泛上下文中使用using @Rusco,我试图扩展我的答案,但我不确定我们是否处于同一波。也许会有助于展示您想要实现的目标。【参考方案2】:

在 Ninject.Web.Common nuget 包中有一个名为 InRequestScope 的扩展方法。

InRequestScope:https://github.com/ninject/Ninject.Web.Common/wiki/InRequestScope

您可以关联 .net core 和 ninject DI 方法 来自https://github.com/ninject/Ninject/wiki/Object-Scopes

【讨论】:

感谢您的回答 Anupam Singh。请再次阅读我的问题。这不是关于 ASP.NET,这不是 Web 应用程序。你没有回答我的问题。我明确说过,至少两次这不是针对 Web 应用程序的,这是关于为 .NET Core 应用程序移植 Ninject 的 InRequestScope,就像 .NET Core DI 正在做的那样。

以上是关于Ninject 中的 .NET Core DI 范围生命周期的主要内容,如果未能解决你的问题,请参考以下文章

使用Ninject进行DI(依赖注入)

在 .Net 3.5 中使用 Ninject 时 System.Core 的 System.Io.FileNotFoundException

依赖注入(DI)和Ninject,Ninject

.NET Core 的 NUnit Entity Framework 集成测试依赖注入问题

使用 Ninject

.NET Core DI 中的异步提供程序