.net core 注册具有多个生存期的服务
在.NETCore2.2应用程序中,我需要一个服务的暂时版本和一个作用域版本 对于“常规”服务,我可以创建两个不同的接口,一个注册为瞬态接口,另一个注册为作用域接口,但如果两者都需要DbContext,这意味着我需要创建两个DbContext(是的,一个可以只是包装器)并同时注册,但这感觉不合适 我使用的是DotnetCore的默认依赖注入框架,我对它不太熟悉。在UnityIoC中,我可以使用命名注册轻松完成这项工作:.net core 注册具有多个生存期的服务,.net-core,dependency-injection,lifetime,ef-core-2.2,.net Core,Dependency Injection,Lifetime,Ef Core 2.2,在.NETCore2.2应用程序中,我需要一个服务的暂时版本和一个作用域版本 对于“常规”服务,我可以创建两个不同的接口,一个注册为瞬态接口,另一个注册为作用域接口,但如果两者都需要DbContext,这意味着我需要创建两个DbContext(是的,一个可以只是包装器)并同时注册,但这感觉不合适 我使用的是DotnetCore的默认依赖注入框架,我对它不太熟悉。在UnityIoC中,我可以使用命名注册轻松完成这项工作: //Note: Pseudo-code void Register(IUni
//Note: Pseudo-code
void Register(IUnityContainer container)
{
container.RegisterType<IMyInterface, MyClass>(
"Transient",
new TransientLifetimeManager()
new InjectionConstructor(
new ResolvedParameter<MyDbContext>("Transient")));
container.RegisterType<IMyInterface, MyClass>(
"PerResolve",
new "PerResolve", new PerResolvedLifetimeManager()()
new InjectionConstructor(
new ResolvedParameter<MyDbContext>(PerResolve)));
container.RegisterType<MyDbContext>("Transient", new TransientLifetimeManager());
container.RegisterType<MyDbContext, MyClass>("PerResolve", new PerResolvedLifetimeManager());
}
//注意:伪代码
无效寄存器(IUnityContainer容器)
{
container.RegisterType(
“暂时的”,
新的TransientLifetimeManager()
新注入构造函数(
新解析参数(“瞬态”);
container.RegisterType(
“佩雷索夫”,
新的“PerResolve”,新的PerResolvedLifetimeManager()
新注入构造函数(
新解析参数(PerResolve);
RegisterType(“Transient”,新TransientLifetimeManager());
RegisterType(“PerResolve”,新的PerResolvedLifetimeManager());
}
优点:使用IServiceProvider,如何要求瞬态分辨率与范围分辨率?实现这一点的最简单方法是使用两个接口,如以下示例所示:
interface IMyScopedInterface
{
void Foo();
}
interface IMyTransientInterface
{
void Foo();
}
class MyClass : IMyTransientInterface, IMyScopedInterface
{
public MyClass(MyDbContext dbContext)
{
}
public void Foo()
{
}
}
然后使用以下命令注册您的类:
services.AddTransient<IMyTransientInterface, MyClass>();
services.AddScoped<IMyScopedInterface, MyClass>();
services.AddTransient();
services.addScope();
您无需对DbContext
执行任何特殊操作即可支持此功能。让我们看看DI系统将如何解决这些服务,看看它是否能够澄清为什么会出现这种情况
IMyScopedInterface
的实例(通常是因为DI系统尝试实例化其构造函数采用IMyScopedInterface
参数的其他服务)IMyScopedInterface
已使用作用域生存期注册,DI系统首先查看其已为当前作用域实例化的服务集合,以查看是否已创建IMyScopedInterface
。该搜索结果是空手而来的,因此DI系统随后继续创建MyClass
的新实例MyClass
的构造函数并确定它需要一个MyDbContext
,因此它通过相同的流递归回来,以获得一个MyDbContext
MyDbContext
的MyClass
实例,然后将该MyClass
对象缓存为当前作用域的一部分,以便同一作用域内的IMyScopedInterface
后续请求可以接收共享对象IMyTransientInterface
,除了DI系统不需要寻找以前实例化的对象实例,并且在构建新的MyClass
实例之后,它根本不缓存它
希望从这个流程中可以清楚地看到,
MyDbContext
的生存期实际上并不重要。如果它注册为transient,那么MyClass
的每个新实例都将获得它自己的唯一实例MyDbContext
。如果MyDbContext
的生存期是限定范围的(这是实体框架中的默认行为),那么,在给定范围内创建的MyClass
的所有实例都将共享一个MyDbContext
实例,而不管MyClass
实例是为IMyScopedInterface
还是IMyTransientInterface实例化的,我想您可能在部分问题上弄错了。当说:“…但是如果两者都需要一个DbContext,这意味着我需要创建两个DbContext(是的,一个可以只是一个包装器)并同时注册这两个…”时,这实际上是不正确的。如果您的DbContext注册了一个作用域生命周期(几乎可以肯定是这样),那么只会为当前作用域创建一个DbContext,MyClass的作用域版本和瞬态版本都会在其构造函数中接收它。我接受了答案,尽管它没有回答问题,因为这是对DI的一个很好的解释,它可以帮助其他开发人员,但在我的例子中,很简单,我没有创建一个范围,但是一个依赖关系需要一个范围。。。