手动解析 InstancePerLifetimeScope 类型时未收到注入实例/不相同

问题描述 投票:0回答:1

我有以下注册码:

private static IContainer BuildContainer()
{
    var builder = new ContainerBuilder();
    // current assembly
    builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

...
    builder.Register(c => new UserSettings(_connectionString)).As<IUserSettings>().**InstancePerLifetimeScope**();
...
    var container = builder.Build();

    **CommonServiceLocator.ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(container));**

    return container;
}

我还使用 Microsoft 的 CommonServiceLocator 来处理一种边缘情况。在“OnActionExecuting”函数中,我设置了 IUserSettings 中的属性之一:

public override void OnActionExecuting(HttpActionContext actionContext)
{
    ...

    var userSettings = actionContext.Request.GetDependencyScope().GetService(typeof(IUserSettings)) as IUserSettings;

    **userSettings.Test = 123;**
}

在整个 MVC 应用程序和一些库(它们是 MVC 应用程序依赖项)中,我可以解析 IUserSettings 的相同对象 - 如果我通过构造函数使用经典 DI。但是当我尝试通过全局服务定位器解析它时:

var settings = ServiceLocator.Current.GetInstance<IUserSettings>();

我得到了 IUserSettings 的一个新实例,而不是请求附带的初始实例。单例实例工作正常,但注册为“InstancePerLifetimeScope”的实例则不行。

有人知道我做错了什么吗?有没有办法使用全局“ServiceLocator”解析 IUserSettings 的同一实例?

autofac resolve lifetime-scoping common-service-locator
1个回答
0
投票

简短的版本是:你无法[轻易]做你想做的事。

如果您还记得您的生命周期范围知识,基于请求的应用程序中的生命周期范围是分层的。

  • 根容器/根生命周期 -
    ServiceLocator
    通常卡在这里。
    • 请求 1 生命周期范围 - 这是控制器参数的来源。
    • 请求 2 个生命周期范围
    • ...
    • 请求 N 个生命周期范围

如果您将某些内容注册为

InstancePerLifetimeScope
,它将在每个“存储桶”中创建一个。

  • 如果您从 root 解析(就像
    ServiceLocator
    所做的那样),您将在那里获得一个实例。
  • 如果您从请求生命周期解析(如控制器中的构造函数),您将从该范围获得一个实例。

但是

ServiceLocator
和请求生命周期范围之间没有“联系”。

现在,

AutofacDependencyResolver
确实有一个
Current
属性
,可以让您获取请求生命周期范围,但请注意,这仅在网络请求的上下文中起作用 - 如果您执行异步操作并且请求在你的工作完成之前结束,该解析器将从你的身下消失。

DI 在很大程度上是“病毒式”的。如果您从 DI 切换到服务位置,您就打破了模式,并且需要一些变通方法和黑客技术。我知道有时这是必需的,只是,当您从一种切换到另一种时,您不会获得尽可能多的“开箱即用”和“正常工作”,显然,这就是正在发生的情况。如果您能坚持使用 DI 并允许根据需要注入请求服务,并且尽可能不通过服务位置,您的情况会更好。

© www.soinside.com 2019 - 2024. All rights reserved.