方法签名IServiceProvider.GetService(Type serviceType)IServiceLocator.GetInstance(Type serviceType)的意图是否有所不同?如果是这样,有什么区别?

我一直将它们视为同等的,但选择使用一种方法来保持一致性。对于两个接口(interface),这似乎是一个足够好的解决方案,但我真的很想知道它们的用法是如何实际使用的,以便可以确保在正确的位置使用正确的接口(interface)。 如果他们的意图实际上是相同的,那么出于相同的目的,是否有理由拥有多组语义? (我知道the GetInstance signature was recommended during the inception of Microsoft.Practices.ServiceLocation ,但这似乎并不是引入重复项的合理理由)。

为什么我很困惑

以下是我在试图找到该问题的答案时发现的一些有时相互矛盾的事实,以及我的解释。我包括这些内容,以便可以在有关该主题的所有已知信息的背景下解决我的问题。

  • MSDN documentation for IServiceProvider 表示GetService(Type serviceType)方法应返回

  • MSDN documentation for IServiceLocator 缺少方法文档,但是VS对象浏览器中GetInstance(Type serviceType)的摘要指出,该方法返回“请求的服务实例”。但是,文档IServiceLocator中也有一个异常(exception)条目,该条目指出如果解析服务实例时发生错误,则应抛出ActivationException
  • ActivationException位于Microsoft.Practices.ServiceLocation命名空间中,该命名空间是在IServiceProvider引入多年后才引入的。因此,可以理解IServiceProvider没有引用该异常。话虽如此,IServiceLocator接口(interface)的文档没有找到任何关于返回null的信息。还不清楚是否缺少所请求的服务类型的实现是否应构成异常(exception)。
  • 是否缺少服务类型的实现会导致ActivationException实现中的IServiceLocator它看起来不像。 IServiceLocatorimplementation template忽略了任何非空后置条件的概念。
  • IServiceLocatorimplementation template还将IServiceProvider.GetService(Type)视为IServiceLocator.GetInstance()的替代语法。这是否算作对Liskov的违反(由于在基类型中未声明的子类型中引发了异常),还是实际上需要实现上的差异而不是在接口(interface)的方法签名上声明的异常?我正在得到的是:我们确定ServiceLocatorImplBaseIServiceLocator实现模板正确地实现了两个接口(interface)吗? 是否可以更好地表示IServiceProvider的接口(interface)意图,将GetInstance调用包装在try块中,并在捕获到异常时返回null
  • 附录:与此相关的另一个问题是IServiceLocator.GetAllInstances(Type)IServiceLocator.GetInstance(Type)的对应关系。具体来说,对于任何类型T,IServiceLocator.GetAllInstances(typeof(T))的实现是否应返回与IServiceLocator.GetInstance(typeof(IEnumerable<>).MakeGenericType(typeof(T))相同的结果? (很容易看出这与IServiceProvider的对应关系如何,但我认为最好是使问题保持​​简单,并且在这种情况下仅比较同一接口(interface)的两种方法。)

    最佳答案

    如您已经提到的,IServiceProvider.GetServiceIServiceLocator.GetInstance之间的区别在于,任何IServiceProvider.GetService实现都应在未注册服务或由于某种原因而无法解决时返回null,而IServiceLocator.GetInstance实现则应引发异常在这种情况下(永远不要返回null)。

    但是请注意我对“应该”一词的使用。随Common Service Locator project(拥有IServiceLocator接口(interface))一起提供的所有CSL适配器(用于Windsor,Spring,Unity和StructureMap等)都不遵循IServiceProvider接口(interface),当您调用其IServiceProvider.GetService方法时它们会引发异常。

    通过违约,CSL的设计人员设法使IServiceProvider接口(interface)完全无用。您现在根本无法再依赖它返回null了,这很糟糕。特别糟糕。我知道遵守契约(Contract)的唯一CSL适配器是Simple Injector adapter,但是由于所有其他实现都被破坏了,因此即使正确实现的适配器在那个时候也没有用,因为您无法安全地交换实现。



    绝对地。他们破坏了接口(interface)协定,并且实现不能相互替代。

    设计师知道这一点,可以从Glenn Blockthis thread的评论中看出:



    由于CSL从未更新过,因此该缺陷从未得到修复。

    关于c# - IServiceLocator.GetInstance(Type)的意图与IServiceProvider.GetService(Type)的意图有何不同?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14864108/

  • 10-10 19:19