【问题标题】:.NET Core DI scope lifetime in NinjectNinject 中的 .NET Core DI 范围生命周期
【发布时间】: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 中实现类似的行为?

【问题讨论】:

标签: c# entity-framework dependency-injection .net-core ninject


【解决方案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 正在做的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多