如果IServiceProvider没有实现ISupportRequiredService,则执行所需的异常抛出行为,如您所料:GetService()调用,如果返回null则抛出异常。
那你应该使用哪种方法?正如我之前所说,理想情况下,两者都可以!
在您自己的代码使用ISeviceProvider通常是你正在使用服务定位器反模式的一个标志,所以一般应避免使用ISeviceProvider。但是,如果由于设计限制而需要(例如,您不能在属性中使用DI),或者作为DI容器配置本身的一部分的情况下,您应该使用哪一种呢?
基于GitHub中要求添加GetRequiredService()的原始问题,以及Jeremy D. Miller先前提出的问题 ,我认为几乎所有情况下的规则是:
使用 GetRequiredService()
减少重复。如果服务不可用,则使用GetRequiredService()会立即抛出异常。如果您使用GetService(),那么您需要在调用代码中检查是否为null,并且通常需要抛出异常。那个空检查代码需要在任何地方重复。
失败很快。如果您在使用GetService()时忘记检查是否为null,那么稍后您的程序可能会以NullReferenceException结束。找出导致异常的原因总是比显式的告诉你的InvalidOperationException更困难,需要做更多的工作。
允许对第三方容器进行高级诊断。StructureMap和其他一些第三方容器的一大好处是,它们能够提供详细的异常消息,说明为什么找不到服务。如果您正在使用GetRequiredService(),则第三方容器本身会生成异常,因此可以提供其他特定于容器的信息。只返回null(带GetService())不会给你进一步的详细的信息。这是引入GetRequiredService()的主要原因。
当然,我已经看到了一些反对GetRequiredService()`的观点,但我认为其中任何一个都不会受到审查:
“我没有使用第三方容器”。如果您正在使用内置容器(未实现ISupportRequiredService),那么您将无法通过使用任何其他诊断获益GetRequiredService()。但是,我认为前两个优势仍然存在,并使GetRequiredService值得使用。此外,如果您以后添加第三方容器,您已经在使用最佳实践了。
“我有可选服务,有时只在DI容器中注册。” 。这可能是使用GetService()唯一有效的理由。如果您的代码只有在注册了给定服务时才能运行,那么您可能需要使用GetService()。但是,如果GetService()返回NULL,我也看到它在使用回退服务时使用。在我看来,这很少是应用程序代码的好模式。回退的编排应该是DI容器配置的一部分,而不是使用服务的位置。
所以,现在你有了 - GetService()与GetRequiredService()之间的对比了。在我进一步挖掘它之前,当我选择一个而不是另一个时,我有点武断,但现在我会确保我总是理所当然的使用GetRequiredService()。
摘要GetService()是IServiceProvider上的唯一方法,ISeviceProvider是ASP.NET核心DI抽象中的中央接口。第三方容器还可以实现可选接口ISupportRequiredService,该接口提供GetRequiredService()方法。当请求的类型serviceType可用时,这些方法的行为相同。如果服务不可用(即它没有注册),则GetService()返回null,而GetRequiredService()抛出一个InvalidOperationException。
GetRequiredService()相对于GetService()的主要好处是当服务不可用时,它允许第三方容器提供额外的诊断信息。因此,在使用第三方容器时最好使用GetRequiredService()。就个人而言,我会在任何地方使用它,即使我只使用内置的DI容器。
原英文链接:https://andrewlock.net/the-difference-between-getservice-and-getrquiredservice-in-asp-net-core/