![](/img/trans.png)
[英]How can I resolve a registered Dependency from an Autofac Container in .NET Core 3.1
[英]How can a dependency (registered in nested LifetimeScope) be resolved from autofac container
有什么方法可以解决容器的依赖关系(实际上是在嵌套的 LifetimeScope 中注册的,而不是在容器中)?
实际执行说明:
我有包含当前用户基本信息的ApplicationContext
类(在其构造函数中注入了IServiceProvider
)。 它首先从serviceProvider
解析IHttpContextAccessor
,然后从httpContextAccessor.HttpContext
提取用户信息。 ApplicationContext
类被注入到所有存储库/服务中。
但是,在一些静态类中,我从静态 IoC 类(包装在其中的 autofac 容器)解析ApplicationContext
类。 我认为这是唯一的解决方案,因为我无法注入静态构造函数。
我正在实现事件总线,我EventBusContext
创建了EventBusContext
类,该类从事件数据接收用户信息。
ApplicationContext
类尝试从IServiceProvider
解析EventBusContext
并仅在它获取HttpContext
为 null 时从中提取用户信息(这意味着此执行不是从 Http Request 开始)。
一旦EventBus
类接收到来自 RabbitMQ 的事件,它就会创建EventBusConext
类,将用户信息添加到其中并动态注册到新创建的嵌套LifetimeScope
然后解析EventHandler
类并调用 Handle 方法(通过反射)。
一切正常! 仅当EventHandler
使用从静态IoC
类解析ApplicationContext
类的任何类时才会出现此问题,因为静态IoC
类在内部尝试从 autofac 容器(包装在其中)解析EventBusContext
但它未能这样做。
我将专注于开始的最初问题:
有什么方法可以解决容器的依赖关系(实际上是在嵌套的 LifetimeScope 中注册的,而不是在容器中)?
最简洁的答案是不。 如果在子作用域中注册/添加了某些内容,则父作用域无法知道它。
Autofac 范围是分层的。有很多关于此的文档,包括一个图表来说明这一点。
试图将其归结为“规则”,我们可以说:
这非常简化,但足以说明这一点。
如果您将内容动态添加到子生命周期范围内,您将只能在该子生命周期范围以及您从那里创建的任何子范围内访问它们。
var builder = new ContainerBuilder();
builder.RegisterType<A>();
var container = builder.Build();
// This will work (though it's recommended you avoid resolving things
// from containers because it can lead to memory leaks).
// https://autofac.readthedocs.io/en/latest/lifetime/index.html
container.Resolve<A>();
// This will NOT work. The container doesn't have B in it.
container.Resolve<B>();
using(var scope1 = container.BeginLifetimeScope(b => b.RegisterType<B>())
{
// This will work. The child scope knows about parent registrations.
scope1.Resolve<A>();
// This will also work. The registration was added to the scope.
scope1.Resolve<B>();
// This will STILL NOT WORK. The parent does NOT know about child scopes.
container.Resolve<B>();
using(var scope2 = scope1.BeginLifetimeScope())
{
// These will work. The child scope knows about parent registrations.
scope2.Resolve<A>();
scope2.Resolve<B>();
// This will STILL NOT WORK.
container.Resolve<B>();
}
}
没有黑客或解决方法。 它是故意分层的。
如果您需要访问请求级别的项目(或者需要动态注册在子生命周期范围内的事物),那么获取它们的唯一方法是从该子生命周期范围或嵌套子项中解析。
更具体的目标:
从实现描述中,您有一些东西故意在请求之外运行并从根容器解析(同样,这不是一个好主意,但它就是这样)。 如果这些东西突然需要通过请求即时注册的项目,那么您基本上有两种选择,这两种选择都是“您需要更改架构/设计”。
实际上,提供一个完全更新的设计或“工作代码”来说明这些事情中的任何一个,与其说是对问题的回答,不如说是一种咨询工作。 然而不幸的是,获取每个请求数据的解决方案意味着您需要更改您的设计。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.