【发布时间】:2013-01-29 14:55:59
【问题描述】:
方法签名IServiceProvider.GetService(Type serviceType) 和IServiceLocator.GetInstance(Type serviceType) 的意图有区别吗?如果有,有什么区别?
我一直将它们视为等效的,但为了保持一致性,我选择使用单一方法。这似乎是处理这两个接口的一个足够好的解决方案,但我真的很想知道它们的实际用途是什么,以便我可以确定我在正确的地方使用了正确的接口。 如果他们的意图实际上是相同的,那么有什么理由为同一个目的使用多组语义?(我理解the GetInstance signature was recommended during the inception of Microsoft.Practices.ServiceLocation,但这看起来并不像一个声音引入重复的原因)。
为什么我很困惑
下面是我在试图找到这个问题的答案时发现的有时相互矛盾的事实的列表,以及我对它的解释。我将这些包括在内,以便可以在有关该主题的所有已知信息的背景下解决我的问题。
-
MSDN documentation for
IServiceProvider表示GetService(Type serviceType)方法应该返回serviceType 类型的服务对象。
- 或 - 如果没有 serviceType 类型的服务对象,则为
null。 MSDN documentation for
IServiceLocator缺少方法文档,但GetInstance(Type serviceType)的 VS 对象浏览器中的摘要说该方法返回“请求的服务实例”。但是,文档IServiceLocator中也有一个异常条目,指出如果解析服务实例时出错,则应抛出ActivationException。ActivationException位于Microsoft.Practices.ServiceLocation命名空间中,该命名空间是在IServiceProvider引入多年后引入的。所以,IServiceProvider没有提到异常是可以理解的。话虽如此,IServiceLocator接口的文档没有说明如果没有找到结果返回null。也不清楚是否缺少所请求的服务类型的实现应构成例外。如果缺少服务类型的实现,是否会导致
IServiceLocator实现中出现ActivationException? 看起来不像。IServiceLocator的 implementation template 忽略任何非空后置条件的概念。IServiceLocator的implementation template 还将IServiceProvider.GetService(Type)视为IServiceLocator.GetInstance()的替代语法。这是否算作违反 Liskov(由于在未在基类型上声明的子类型中抛出异常),或者,这实际上需要实现差异而不是接口方法签名上声明的异常?我的意思是:我们确定IServiceLocator的ServiceLocatorImplBase实现模板正确实现了这两个接口吗? 是否可以更好地表示IServiceProvider的接口意图?将GetInstance调用包装在try 块中,并在捕获到异常时返回null?附录:与此相关的另一个问题是
IServiceLocator.GetAllInstances(Type)与IServiceLocator.GetInstance(Type)的对应关系。具体来说,对于任何类型 T,IServiceLocator.GetAllInstances(typeof(T))的实现是否应该返回与IServiceLocator.GetInstance(typeof(IEnumerable<>).MakeGenericType(typeof(T))相同的结果?(很容易看出这与IServiceProvider对应关系如何,但我认为这是最好保持问题简单,只比较这种情况下同一接口的两种方法。)
【问题讨论】:
-
.NET IServiceProvider 的起源是 COM 的 IServiceProvider (msdn.microsoft.com/en-us/library/cc678965(v=vs.85).aspx)。它或多或少是这个想法的一个端口(请参阅相关的 COM 文档以了解有关原始意图的一些见解)。至于 ServiceLocator 之一,也许他们只是希望 GetInstance 重载具有相同的名称。 ServiceLocator 并不是真正的 .NET 框架的一部分。它是 Microsoft PAG 小组的插件。
标签: c# dependency-injection service-locator base-class-library common-service-locator