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

时间:2012-02-03 00:16:28

标签: asp.net-mvc-3 unity-container service-locator

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

ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));

3 个答案:

答案 0 :(得分:12)

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

虽然我完全同意“服务地点是一种反模式”的口头禅,但这条规则肯定有例外。

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

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

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

  1. WCF IEndpointBehavior或IClientMessageInspector的实现
  2. WPF IValueConverter的实现
  3. 或者您可能不一定想要从类中访问“服务”,但您只想编写可单元测试的代码,但由于某种原因,该类根本无法实现(或者不是因为它通常由.NET Framework构建,所以你将自定义代码提取到一个可测试的类中,并使用ServiceLocator在不可测试的类中解析它。
  4. 请注意,此行并不理想:

    ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));
    

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

    IServiceLocator locator = new UnityServiceLocator(container);
    ServiceLocator.SetLocatorProvider(() => locator);
    

答案 1 :(得分:7)

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

答案 2 :(得分:1)

与人们谈论的是相同的反模式。该行所做的就是将服务定位器提供程序设置为UnityServiceLocator的实例,即使用ISerivceLocator的Unity实现。 (可选)如果您希望自己的实现是IServiceLocator,可以使用它而不是UnityServiceLocator。

出于here

列出的各种原因,使用服务定位器被视为不良做法