c# - 服务定位器反模式适用于工厂注册

标签 c# rest dependency-injection .net-core service-locator

我正在创建一个 REST 框架,我想知道是否可以提供对服务提供者的访问,因为它将在工厂中使用。我有一个通用服务,它有在创建和更新时触发的事件

public event Func<object, TDTO, Task> CreateEvent;

protected virtual async Task OnCreated(TDTO dto)
{
    await ServiceEventHandlerRule.OnServiceEvent(CreateEvent, this, dto);
}

public async Task<TDTO> Create(TDTO dto)
{
    var entity = this.DtoToEntity(dto, new TEntity());
    this._context.Set<TEntity>().Add(entity);

    dto = await this.SaveEntity(entity);
    await OnCreated(dto);
    return dto;
}

我正在工厂的服务上注册事件,目前我正在公开一个 Func<IServiceProvider, Object, TDto>事件注册看起来像这样,这发生在我的 startup.cs 中:

var serviceConfig = new ServiceConfiuration<User, UserDTO>();
serviceConfig.EventMapping.AddCreateEvent(async (sp, obj, dto) => {
    var hubTaskQueue = sp.GetService<IHubServiceTaskQueue>();
    hubTaskQueue.QueueCreate<THub, TDTO>(dto);
});
services.AddScopedRestService(serviceConfig);

用户将需要为他们的事件访问一些额外的依赖项,所以我给了他们访问 IServiceProvider 的权限。 ,

在注册期间使用服务位置模式有什么缺点?

我应该屏蔽 IServiceProvider 并进行一些通用重载以自动解决它们的依赖关系吗?

最佳答案

Dependency Injection Principles, Practices, and Patterns ,我们将服务定位器定义为:

A Service Locator supplies application components outside the Composition Root with access to an unbounded set of Volatile Dependencies. [Chapter 5.2]

组合根是应用程序中模块组合在一起的单个逻辑位置。您可以在 this excerpt 中找到关于组合根的详细说明。摘自本书。

关于您的问题,服务定位器定义的重要部分是:“组合根之外”。换句话说,从 Composition Root 访问一组无限制的 Volatile Dependencies 是可以的,并且不是 Service Locator 反模式的实现。然而,在组合根之外访问它们是一种反模式。

因此,为了回答您的问题,只要您的工厂实现 是组合根的一部分,您就可以安全地让您的工厂依赖容器或解决无限依赖集的抽象。

您可以通过在应用程序逻辑附近放置工厂抽象来实现这一点,同时在应用程序的启动程序集中创建工厂实现。

Users will need access to a few extra dependencies for their events so I've given them access to the IServiceProvider, What is the downside of using the Service Location Pattern During Registration?

如果依赖于 IServiceProvider 的代码不是 Composition Root 的一部分,它们就会使用 Service Locator 反模式,这应该被阻止。服务定位器反模式的主要问题是:

  • 该模块作为冗余依赖项拖拽服务定位器。
  • 该模块使它的依赖关系变得不明显。这使得此类模块更难测试,掩盖了类可能过于复杂的事实,并且更难以验证依赖关系图的正确性,因为依赖关系是延迟获取的。

相反,您应该让这些用户将他们的依赖项定义为构造函数参数。

关于c# - 服务定位器反模式适用于工厂注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51183742/

相关文章:

C# ASP .NET MVC 3单例构造函数调用两次

c# - 我如何找到有时会卡住的程序中的错误位置

javascript - 客户端调用的 api 方法内的 HTTP GET

javascript - 由于找不到模块而将模块注入(inject) Angular

spring - 如何将 spring 管理的服务 bean 注入(inject) Apache CXF Servlet

java - 构建Antlr时,Visual Studio在未命名文件的情况下给出错误 "cannot find the file specified"

c# - 如何添加自定义 TFS CheckinNoteDefinitions?

rest - 关于 REST 全栈框架的建议?

rest - 使用带有 Sails.js 的 REST API 的 CSRF 保护

spring - 将 bean Autowiring 到 JSF 托管 bean 时为空指针