微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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从未被更新.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


原文地址:http://msdn.microsoft.com/en-us/magazine/cc163791.aspx 原文发布日期: 9/19/2005 原文已经被 Microsoft 删除了,收集过程中发现很多文章图都不全,那是因为原文的图都不全,所以特收集完整全文。 目录 前言 CLR启动程序
前言 随着近些年微服务的流行,有越来越多的开发者和团队所采纳和使用,它的确提供了很多的优势也解决了很多的问题,但是我们也知道也并不是银弹,提供优势的同时它也给我们的开发人员和团队也带来了很多的挑战。 为了迎接或者采用这些新技术,开发团队需要更加注重一些流程或工具的使用,这样才能更好的适应这些新技术所
最近因为比较忙,好久没有写博客了,这篇主要给大家分享一下PLINQ中的分区。上一篇介绍了并行编程,这边详细介绍一下并行编程中的分区和自定义分区。 先做个假设,假设我们有一个200Mb的文本文件需要读取,怎么样才能做到最优的速度呢?对,很显然就是拆分,把文本文件拆分成很多个小文件,充分利用我们计算机中
在多核CPU在今天和不久的将来,计算机将拥有更多的内核,Microsoft为了利用这个硬件特性,于是在Visual Studio 2010 和 .NET Framework 4的发布及以上版本中,添加了并行编程这个新特性,我想它以后势必会改变我们的开发方式。 在以前或者说现在,我们在并行开发的时候可
c语言输入成绩怎么判断等级
字符型数据在内存中的存储形式是什么
c语言怎么求字符串的长度并输出
c语言函数的三种调用方式是什么
c语言中保留两位小数怎么表示
double的输入格式符是什么