c# – IServiceLocator.GetInstance(Type)的意图与IServiceProvider.GetService(Type)的意图不同?

前端之家收集整理的这篇文章主要介绍了c# – IServiceLocator.GetInstance(Type)的意图与IServiceProvider.GetService(Type)的意图不同?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
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)方法应该返回

A service object of type serviceType.
-or-

null if there is no service object of type serviceType.

> 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的对应关系如何,但是我认为保持这个问题的简单性比较好,只比较同一个接口的两种方法.)

解决方法

正如您已经指出的那样,IServiceProvider.GetService和IServiceLocator.GetInstance之间的区别在于,当服务未注册时,任何IServiceProvider.GetService实现都应返回null,或者由于任何原因而无法解决该问题,而IServiceLocator.GetInstance实现另一方面应该在这种情况下抛出异常(并且永远不会返回null).

但请注意我使用“应该”一词. Common Service Locator project(拥有IServiceLocator接口)随附的所有CSL适配器(适用于Windsor,Spring,Unity和StructureMap等)不遵守IServiceProvider接口,并在调用其IServiceProvider.GetService方法时引发异常.

通过打破合同,CSL的设计人员设法使IServiceProvider接口无用.你现在根本无法依靠它返回null,这是坏的.特别糟糕.我所知道的唯一CSL适配器是Simple Injector adapter,但是由于所有其他实现都被破坏,即使这个正确实现的适配器在这一点上是无用的,因为没有办法可以安全地交换实现.

Does this count as a violation of Liskov

绝对.他们打破了接口合同,实现方式不能相互代替.

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

Sounds like we might have messed up here. The idea of throwing an
exception was an explicit design goal that we all agreed on. Making it
implement IServiceProvider was more of a convenience,but sounds like
this was overlooked.

缺陷从未被修复过,因为CSL从未被更新.

猜你在找的C#相关文章