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 DIscope
生命周期设置如何工作?它的生命周期是什么?
是否可以在 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 范围生命周期的主要内容,如果未能解决你的问题,请参考以下文章
在 .Net 3.5 中使用 Ninject 时 System.Core 的 System.Io.FileNotFoundException