为什么Unity使用服务定位器?

Tra*_*s J 6 unity-container service-locator asp.net-mvc-3

我在几个教程中看到了这行代码,用于在asp.net mvc3中使用Unity.我的印象是服务定位器是反模式而不是最佳实践.这个服务定位器是否定义了反模式以外的定义,或者这行代码/此实现被认为是不好的做法.

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));
Run Code Online (Sandbox Code Playgroud)

G. *_*ard 12

老问题,但为了别人的利益:

虽然我完全同意"服务地点是一种反模式"的口头禅,但该规则肯定有例外.

当您使用依赖注入(如Unity)时,是的,当然不使用ServiceLocator并且仅对所有服务类使用构造函数注入.(除了像DTO这样的值对象之外,不要使用"new".)

但是,有些情况下您根本无法使用构造函数注入,然后访问服务的唯一方法是使用变通方法直接访问Unity容器,在这种情况下,ServiceLocator是一种很好的标准方法来完成那.当您没有实例化类(或更具体地,它不是由Unity实例化)而是通过.NET框架实例化时就是这种情况.

ServiceLocator可能有用的几个简单示例是访问Unity容器中注册的服务:

  1. WCF IEndpointBehavior或IClientMessageInspector的实现
  2. WPF IValueConverter的实现
  3. 或者您可能不一定想要从类中访问"服务",但您只是想编写可单元测试的代码,但由于某种原因,该类根本无法实现(或不容易),因为它通常由.NET Framework构造,因此您将自定义代码提取到可测试的类中,并使用ServiceLocator在不可测试的类中解析它.

请注意,此行不理想:

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));
Run Code Online (Sandbox Code Playgroud)

每次访问Current时,ServiceLocator.Current属性都将执行提供的委托,即每次都会创建一个新的UnityServiceLocator.相反,您可能想要这样做:

IServiceLocator locator = new UnityServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => locator);
Run Code Online (Sandbox Code Playgroud)


Seb*_*ber 7

如果您创建一个与容器无关的框架,那么服务定位器(尽管它应该是应用程序中的No-Go)是一个额外的间接层,允许您将Unity换成不同的东西.此外,使用服务定位器不会强制使用DI来使用该框架的应用程序.


Sai*_*dla 2

这与人们谈论的反模式是一样的。该行所做的就是将服务定位器提供程序设置为 UnityServiceLocator 的实例,即使用 ISerivceLocator 的 Unity 实现。或者,如果您愿意,您可以拥有自己的实现 IServiceLocator 并使用它来代替 UnityServiceLocator。

由于此处列出的各种原因,使用服务定位器被认为是一种不好的做法

  • 如果您使用 IOC 容器,如何找到该容器? (3认同)