方法签名IServiceProvider.GetService(Type serviceType)
和IServiceLocator.GetInstance(Type serviceType)
的意图是否有所不同?如果是这样,有什么区别?
我一直将它们视为同等的,但选择使用一种方法来保持一致性。对于两个接口(interface),这似乎是一个足够好的解决方案,但我真的很想知道它们的用法是如何实际使用的,以便可以确保在正确的位置使用正确的接口(interface)。 如果他们的意图实际上是相同的,那么出于相同的目的,是否有理由拥有多组语义? (我知道the GetInstance
signature was recommended during the inception of Microsoft.Practices.ServiceLocation
,但这似乎并不是引入重复项的合理理由)。
为什么我很困惑
以下是我在试图找到该问题的答案时发现的一些有时相互矛盾的事实,以及我的解释。我包括这些内容,以便可以在有关该主题的所有已知信息的背景下解决我的问题。
IServiceProvider
表示GetService(Type serviceType)
方法应返回IServiceLocator
缺少方法文档,但是VS对象浏览器中GetInstance(Type serviceType)
的摘要指出,该方法返回“请求的服务实例”。但是,文档IServiceLocator
中也有一个异常(exception)条目,该条目指出如果解析服务实例时发生错误,则应抛出ActivationException
。 ActivationException
位于Microsoft.Practices.ServiceLocation
命名空间中,该命名空间是在IServiceProvider
引入多年后才引入的。因此,可以理解IServiceProvider
没有引用该异常。话虽如此,IServiceLocator
接口(interface)的文档没有找到任何关于返回null
的信息。还不清楚是否缺少所请求的服务类型的实现是否应构成异常(exception)。 ActivationException
实现中的IServiceLocator
? 它看起来不像。 IServiceLocator
的implementation template忽略了任何非空后置条件的概念。 IServiceLocator
的implementation template还将IServiceProvider.GetService(Type)
视为IServiceLocator.GetInstance()
的替代语法。这是否算作对Liskov的违反(由于在基类型中未声明的子类型中引发了异常),还是实际上需要实现上的差异而不是在接口(interface)的方法签名上声明的异常?我正在得到的是:我们确定ServiceLocatorImplBase
的IServiceLocator
实现模板正确地实现了两个接口(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.GetService
和IServiceLocator.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 Block对this thread的评论中看出:
由于CSL从未更新过,因此该缺陷从未得到修复。
关于c# - IServiceLocator.GetInstance(Type)的意图与IServiceProvider.GetService(Type)的意图有何不同?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14864108/