【问题标题】:Is resolving a service in Startup.cs a service locator pattern?解析 Startup.cs 中的服务是服务定位器模式吗?
【发布时间】:2017-03-03 12:18:51
【问题描述】:

我已阅读 Mark Seemann 的 Service Locator: roles vs mechanics,但我无法决定什么。这是GetRequiredService 方法,它用于Startup.cs 中的ConfigureServices 方法(如果我理解正确的话,就是composition root),一个服务定位器:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddScoped<IRepository, MyRepository>();

    services.AddAuthorization(options =>
    {
        var myPolicy = services.BuildServiceProvider()
            .GetRequiredService<IRepository>().GetMyPolicy();

        options.AddPolicy("MyPolicy", policy => policy.AddRequirements(myPolicy));
    });
}

【问题讨论】:

  • 这篇文章是DI Friendly Framework。一个框架通常必须提供至少一个扩展点(通常是一个抽象工厂),容器可以在其中注入组合根内部,否则它不会知道有关最终用户组件的任何信息。这不是服务定位器 - 它是与任何类型的框架集成的现实。
  • 这里的大警告:您在调用BuildServiceProvider 时应该非常小心,因为这会强制创建一个具有自己的单例集的不同容器实例。这可能会导致非常奇怪的行为并且难以追踪错误。相反,更喜欢在 AddAuthorization 委托中手动创建 MyRepository
  • @Steven:我实际上使用 SimpleInjector 我将使用它进行服务解析,我只是使用本机 .NET 容器作为示例。不过感谢您的警告。

标签: design-patterns dependency-injection asp.net-core-mvc inversion-of-control service-locator


【解决方案1】:

正如 Mark here 所解释的:

封装在组合根中的 DI 容器不是服务定位器 - 它是一个基础架构组件。

Startup 类是组合根的一部分。这意味着调用GetRequiredService不是服务定位器反模式的实现。

【讨论】:

  • 你肯定是 Mark Seemann 的粉丝!我看到你要么评论任何东西,要么回答你总是用他作为参考的问题:D
  • @MatiasFidemraizer:根本不是粉丝。但是为什么要尝试重复别人已经清楚表达的东西。
  • 我不确定我是否 100% 同意你的观点。当我们试图用自己的话来解释一些概念时,我觉得我们在挑战自己,以验证我们是否真的理解我们试图描述的东西。 BTW不要误会我的意思!我并不是说您的答案是错误的或质量低下。我刚刚注意到,每当我看到您评论 Q 或 A,或回答问题时,我看到您引用 Mark Seemann 的话:D
【解决方案2】:

在某些极端情况下,服务定位器是不可避免的。

并非所有框架或库都准备好成为依赖注入链的一部分,因此您需要直接使用 IoC 容器来定位整个服务。

尽量避免将服务定位器作为实际应用程序代码的一部分,您负责在软件架构方面尽力而为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-24
    • 2016-03-28
    • 2020-04-22
    • 2017-06-17
    • 1970-01-01
    • 2011-11-17
    • 2018-03-14
    • 2010-11-28
    相关资源
    最近更新 更多