方法签名的意图是否存在差异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)方法应该返回
A service object of type serviceType.
-or-
null if there is no service object of type serviceType.
MSDN documentation for IServiceLocator 缺少方法文档,但 VS 对象浏览器中的摘要 GetInstance(Type serviceType)表示该方法返回“请求的服务实例”。但是,文档中也有异常条目IServiceLocator那说 ActivationException如果解析服务实例时出现错误,则应抛出该异常。
ActivationException位于 Microsoft.Practices.ServiceLocation在 IServiceProvider 之后引入的 namespace 被介绍。所以,IServiceProvider 是可以理解的不指异常。也就是说,IServiceLocator接口(interface)的文档没有提到返回 null如果没有找到结果。还不清楚所请求服务类型的实现缺失是否应该构成异常。
如果缺少服务类型的实现会导致 ActivationException在IServiceLocator实现? 看起来不像。 implementation template对于 IServiceLocator忽略任何非空后置条件的概念。
implementation template对于 IServiceLocator也对待IServiceProvider.GetService(Type)作为 IServiceLocator.GetInstance() 的替代语法.这是否算作违反 Liskov(由于在未在基类型上声明的子类型中抛出异常),或者,这实际上需要在实现上有所不同,而不是在接口(interface)的方法签名上声明异常吗?我的意思是:我们确定 ServiceLocatorImplBase IServiceLocator 的实现模板是否正确实现了这两个接口(interface)? 它是否能更好地表示接口(interface)对 IServiceProvider 的意图?包装 GetInstance调用 try block ,并返回 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 随附的所有 CSL 适配器(用于 Windsor、Spring、Unity 和 StructureMap 等) (它拥有 IServiceLocator 接口(interface))不遵守 IServiceProvider 接口(interface),当您调用它们的 IServiceProvider.GetService 方法时,它们会抛出异常。
通过破坏契约,CSL 的设计者设法使 IServiceProvider 接口(interface)完全无用。您现在不能再依赖它返回 null,这很糟糕。特别糟糕。我所知道的唯一遵守契约(Contract)的 CSL 适配器是 Simple Injector adapter ,但是由于所有其他实现都被破坏了,即使这个正确实现的适配器此时也没有用,因为您无法安全地交换实现。
Does this count as a violation of Liskov
当然。它们破坏了接口(interface)契约,并且实现不能相互替代。
设计者知道这一点,从Glenn Block可以看出对 this 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# - IServiceLocator.GetInstance(Type) 的意图与 IServiceProvider.GetService(Type) 的意图有何不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14864108/
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
在我的系统中,我已经定义了STI。Dog继承自Animal,在animals表中有一个type列,其值为"Dog"。现在我想让SpecialDog继承自dog,只是为了在某些特殊情况下稍微修改一下行为。数据还是一样。我需要通过SpecialDog运行的所有查询,以返回数据库中类型为Dog的值。我的问题是因为我有一个type列,rails将WHERE"animals"."type"IN('SpecialDog')附加到我的查询中,所以我不能获取原始的Dog条目。所以我想要的是以某种方式覆盖rails在通过SpecialDog访问数据库时使用的值,使其表现得像Dog。有没有办法覆盖用于类型
如何将自己的字段类型添加到formtastic中?例如,我需要一个自定义的日期时间输入,我想要这样的东西::my_date%>这显然是行不通的,因为formtastic不知道:my_date(只有:boolean、:string、:datetime等等...)但是我怎样才能添加额外的输入类型呢? 最佳答案 您需要添加自定义输入法:classMyCustomFormtasticFormBuilder这非常适合新的HTML5输入类型。你可以这样使用它:MyCustomFormtasticFormBuilderdo|f|%>:my_dat
我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume
我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用
什么是Linq聚合方法的ruby等价物。它的工作原理是这样的varfactorial=new[]{1,2,3,4,5}.Aggregate((acc,i)=>acc*i);每次将数组序列中的值传递给lambda时,变量acc都会累积。 最佳答案 这在数学以及几乎所有编程语言中通常称为折叠。它是更普遍的变形概念的一个实例。Ruby从Smalltalk中继承了这个特性的名称,它被称为inject:into:(像aCollectioninject:aStartValueinto:aBlock一样使用。)所以,在Ruby中,它称为inj
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭8年前。Improvethisquestion几年前我去学校学习编程,毕业后我找到了一份系统管理方面的工作,这就是我职业生涯的方向。我想重新开始某种开发,并且一直在“玩”C#和ASP.NET,但我已经听到很多关于其他"new"语言的讨论(新的意思是它们是新的)我)喜欢Ruby和F#。我想我想知道我是否在浪费时间学习主要的MS语言,而不是成为一名通才。很长一段时间没有离开开发社区(如果我曾经离开过的话)让我在潮流中挣扎,我不想落在时代的