我在几个教程中看到了这行代码,用于在asp.net mvc3中使用Unity。我的印象是服务定位器是反模式而不是最佳实践。这个服务定位器是非定义的反模式,还是这行代码/这个实现被认为是不好的做法。
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(Container));
答案 0 :(得分:12)
老问题,但为了别人的利益:
虽然我完全同意“服务地点是一种反模式”的口头禅,但这条规则肯定有例外。
当您使用依赖注入(如Unity)时,是的,当然不使用ServiceLocator并且仅对所有服务类使用构造函数注入。 (另外,除了像DTO这样的值对象之外,不要使用“new”。)
但是,有些情况下您根本无法使用构造函数注入,然后访问服务的唯一方法是使用变通方法直接访问Unity容器,在这种情况下,ServiceLocator是一个很好的标准实现这一目标的方法。当您没有实例化类(或者更具体地说,它不是由Unity实例化)而是通过.NET框架实例化时就是这种情况。
ServiceLocator可能有用的一些简单示例是访问Unity容器中注册的服务:
请注意,此行并不理想:
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
列出的各种原因,使用服务定位器被视为不良做法