重新整理.net core 计1400篇[九] (.net core 中的依赖注入的服务的消费)
前言
包含服务注册信息IServiceCollection 集合最终被用来创建作为依赖注入容器的IServiceProvider 对象。
当需要创建某个服务实例的时候(服务消费),我们通过指定服务类型调用IServiceProvider 接口GetService 方法即可。
那么来看下和IServiceProvider 相关的东西吧。
IServiceProvider
这里面只有一个提供服务的方法:
/// <summary>Defines a mechanism for retrieving a service object; that is, an object that provides custom support to other objects.</summary>
public interface IServiceProvider
{
/// <summary>Gets the service object of the specified type.</summary>
/// <param name="serviceType">An object that specifies the type of service object to get.</param>
/// <returns>A service object of type <paramref name="serviceType">serviceType</paramref>.
/// -or-
/// null if there is no service object of type <paramref name="serviceType">serviceType</paramref>.</returns>
object GetService(Type serviceType);
}
在创建IServiceProvider的对象创建上,有三个构造函数:
public static class ServiceCollectionContainerBuilderExtensions
{
/// <summary>
/// Creates a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> containing services from the provided <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />.
/// </summary>
/// <param name="services">The <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" /> containing service descriptors.</param>
/// <returns>The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" />.</returns>
public static ServiceProvider BuildServiceProvider(this IServiceCollection services)
{
return services.BuildServiceProvider(ServiceProviderOptions.Default);
}
/// <summary>
/// Creates a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> containing services from the provided <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />
/// optionally enabling scope validation.
/// </summary>
/// <param name="services">The <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" /> containing service descriptors.</param>
/// <param name="validateScopes">
/// <c>true</c> to perform check verifying that scoped services never gets resolved from root provider; otherwise <c>false</c>.
/// </param>
/// <returns>The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" />.</returns>
public static ServiceProvider BuildServiceProvider(this IServiceCollection services, bool validateScopes)
{
return services.BuildServiceProvider(new ServiceProviderOptions
{
ValidateScopes = validateScopes
});
}
/// <summary>
/// Creates a <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" /> containing services from the provided <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" />
/// optionally enabling scope validation.
/// </summary>
/// <param name="services">The <see cref="T:Microsoft.Extensions.DependencyInjection.IServiceCollection" /> containing service descriptors.</param>
/// <param name="options">
/// Configures various service provider behaviors.
/// </param>
/// <returns>The <see cref="T:Microsoft.Extensions.DependencyInjection.ServiceProvider" />.</returns>
public static ServiceProvider BuildServiceProvider(this IServiceCollection services, ServiceProviderOptions options)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
if (services == null)
{
throw new ArgumentNullException("services");
}
if (options == null)
{
throw new ArgumentNullException("options");
}
return new ServiceProvider((IEnumerable<ServiceDescriptor>)services, options);
}
}
我们看到无论其如何构造,那么都有一个ServiceProviderOptions配置类。
这个配置我前面8中解释过,就是对注入服务的范围检测。
那么还有一个重要的问题,难道我们只能根据getservice 去获取服务对象?来看看获取服务的扩展。
查看ServiceProviderServiceExtensions类:
里面有一些:
public static T GetService<T>(this IServiceProvider provider)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
if (provider == null)
{
throw new ArgumentNullException("provider");
}
return (T)provider.GetService(Type.GetTypeFromHandle(typeof(T).TypeHandle));
}
/// <summary>
/// Get service of type <paramref name="serviceType" /> from the <see cref="T:System.IServiceProvider" />.
/// </summary>
/// <param name="provider">The <see cref="T:System.IServiceProvider" /> to retrieve the service object from.</param>
/// <param name="serviceType">An object that specifies the type of service object to get.</param>
/// <returns>A service object of type <paramref name="serviceType" />.</returns>
/// <exception cref="T:System.InvalidOperationException">There is no service of type <paramref name="serviceType" />.</exception>
public static object GetRequiredService(this IServiceProvider provider, Type serviceType)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
if (provider == null)
{
throw new ArgumentNullException("provider");
}
if (serviceType == (Type)null)
{
throw new ArgumentNullException("serviceType");
}
ISupportRequiredService supportRequiredService = provider as ISupportRequiredService;
if (supportRequiredService != null)
{
return supportRequiredService.GetRequiredService(serviceType);
}
object service = provider.GetService(serviceType);
if (service == null)
{
throw new InvalidOperationException(Resources.FormatNoServiceRegistered(serviceType));
}
return service;
}
/// <summary>
/// Get service of type <typeparamref name="T" /> from the <see cref="T:System.IServiceProvider" />.
/// </summary>
/// <typeparam name="T">The type of service object to get.</typeparam>
/// <param name="provider">The <see cref="T:System.IServiceProvider" /> to retrieve the service object from.</param>
/// <returns>A service object of type <typeparamref name="T" />.</returns>
/// <exception cref="T:System.InvalidOperationException">There is no service of type <typeparamref name="T" />.</exception>
public static T GetRequiredService<T>(this IServiceProvider provider)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
if (provider == null)
{
throw new ArgumentNullException("provider");
}
return (T)provider.GetRequiredService(Type.GetTypeFromHandle(typeof(T).TypeHandle));
}
/// <summary>
/// Get an enumeration of services of type <typeparamref name="T" /> from the <see cref="T:System.IServiceProvider" />.
/// </summary>
/// <typeparam name="T">The type of service object to get.</typeparam>
/// <param name="provider">The <see cref="T:System.IServiceProvider" /> to retrieve the services from.</param>
/// <returns>An enumeration of services of type <typeparamref name="T" />.</returns>
public static IEnumerable<T> GetServices<T>(this IServiceProvider provider)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
if (provider == null)
{
throw new ArgumentNullException("provider");
}
return provider.GetRequiredService<IEnumerable<T>>();
}
其余的可以自己去查看。
服务的创建
我们知道服务的创建一般都是ioc自动选择的,那么假如我们一个class 里面有多个构造函数,那么会选择哪一个呢?
public interface IFoo { }
public interface IBar { }
public interface IBaz { }
public interface IQux { }
public class Foo : IFoo { }
public class Bar : IBar { }
public class Baz : IBaz { }
public class Qux : IQux
{
public Qux(IFoo foo) => Console.WriteLine("Selected constructor: Qux(IFoo)");
public Qux(IFoo foo, IBar bar) => Console.WriteLine("Selected constructor: Qux(IFoo, IBar)");
public Qux(IFoo foo, IBar bar, IBaz baz) => Console.WriteLine("Selected constructor: Qux(IFoo, IBar, IBaz)");
}
static void Main()
{
new ServiceCollection()
.AddTransient<IFoo, Foo>()
.AddTransient<IBar, Bar>()
.AddTransient<IQux, Qux>()
.BuildServiceProvider()
.GetServices<IQux>();
Console.ReadKey();
}
上面Qux有三个控制类,那么选择哪一个呢?
看下结果:

那么为什么会是这一个呢?
第一:IBaz类型没有注册,那么会排除掉Qux(IFoo foo, IBar bar, IBaz baz)
第二就是里面的一个规则:每一个候选构造参数类型的集合都是这个构造函数参数类型的子集。
好的,那么好了,剩下:Qux(IFoo foo, IBar bar) 包含了Qux(IFoo foo) 那么就是Qux(IFoo foo, IBar bar),如果没有包含全部子集的那么就会报错。
Qux(IFoo foo, IBar bar) 也就是超集的意思。
改一下:
public interface IFoo { }
public interface IBar { }
public interface IBaz { }
public interface IQux { }
public class Foo : IFoo { }
public class Bar : IBar { }
public class Baz : IBaz { }
public class Qux : IQux
{
public Qux(IFoo foo, IBaz baz) => Console.WriteLine("Selected constructor: Qux(IFoo, IBar)");
public Qux(IFoo foo, IBar bar) => Console.WriteLine("Selected constructor: Qux(IFoo, IBar, IBaz)");
}
static void Main()
{
new ServiceCollection()
.AddTransient<IFoo, Foo>()
.AddTransient<IBar, Bar>()
.AddTransient<IBaz,Baz>()
.AddTransient<IQux, Qux>()
.BuildServiceProvider()
.GetServices<IQux>();
Console.ReadKey();
}
这时候报错为:

下一节
服务的生命周期
重新整理.net core 计1400篇[九] (.net core 中的依赖注入的服务的消费)的更多相关文章
- ASP.NET CORE MVC 2.0 如何在Filter中使用依赖注入来读取AppSettings,及.NET Core控制台项目中读取AppSettings
问: ASP.NET CORE MVC 如何在Filter中使用依赖注入来读取AppSettings 答: Dependency injection is possible in filters as ...
- 在.NET Core控制台程序中使用依赖注入
之前都是在ASP.NET Core中使用依赖注入(Dependency Injection),昨天遇到一个场景需要在.NET Core控制台程序中使用依赖注入,由于对.NET Core中的依赖注入机制 ...
- ASP.NET Core中的依赖注入(2):依赖注入(DI)
IoC主要体现了这样一种设计思想:通过将一组通用流程的控制从应用转移到框架之中以实现对流程的复用,同时采用"好莱坞原则"是应用程序以被动的方式实现对流程的定制.我们可以采用若干设计 ...
- ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【解读ServiceCallSite 】
通过上一篇的介绍我们应该对实现在ServiceProvider的总体设计有了一个大致的了解,但是我们刻意回避一个重要的话题,即服务实例最终究竟是采用何种方式提供出来的.ServiceProvider最 ...
- NET Core 中的依赖注入
NET Core 中的依赖注入 [共7篇] 一.控制反转(IoC) ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制, ...
- .NET CORE——Console中使用依赖注入
我们都知道,在 ASP.NET CORE 中通过依赖注入的方式来使用服务十分的简单,而在 Console 中,其实也只是稍微绕了个小弯子而已.不管是内置 DI 组件或者第三方的 DI 组件(如Auto ...
- Asp.net core中的依赖注入
使用服务 在Asp.net core的Controller中,可以通过如下两种方式获取系统注入的服务: 构造函数 可以直接在构造函数中传入所依赖的服务,这是非常常见的DI注入方式. public Va ...
- ASP.NET Core Web 应用程序系列(一)- 使用ASP.NET Core内置的IoC容器DI进行批量依赖注入(MVC当中应用)
在正式进入主题之前我们来看下几个概念: 一.依赖倒置 依赖倒置是编程五大原则之一,即: 1.上层模块不应该依赖于下层模块,它们共同依赖于一个抽象. 2.抽象不能依赖于具体,具体依赖于抽象. 其中上层就 ...
- 第10章 带有依赖注入的服务配置(ASP.NET Core in Action, 2nd Edition)
第2部分 构建完整的应用程序 我们在第一部分中讨论了很多内容.您看到了ASP.NET Core应用程序是如何由中间件组成的,我们主要关注RazorPages框架.您了解了如何使用Razor语法构建传统 ...
- ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入
原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...
随机推荐
- Nfs 共享存储搭建
Nfs 共享存储搭建 为了实现不同操作系统中的数据共享,我们一般会搭建一些用于文件共享的服务器,nfs服务器就是其中一种,它实现的是linux与linux之间的共享.今天我将把如何在linux系统搭建 ...
- matting tool by cs - 视频扣绿幕 1.4 - 软件推荐
本地软件,还没用,先留个档,试试 第一个下载还套了个广告壳,醉了,但是能用 https://www.123pan.com/s/X3jA-POMQv 这个装了,是原版,没套壳 https://pan.b ...
- 让 js 失效 Chrome F12 右上角 settings - Preferences - Debugger - Disable JavaScript
说的可能比较长,实际上,F12 右上角 - 右小角 还是挺好找的.
- vivo统一接入网关VUA转发性能优化实践
作者:vivo 互联网服务器团队 - Qiu Xiangcun 本文将探讨如何通过使用Intel QuickAssist Technology(QAT)来优化VUA的HTTPS转发性能.我们将介绍如何 ...
- DWR之入门实例(一)
DWR(Direct Web Remoting)是一个WEB远程调用框架.利用这个框架可以让AJAX开发变得很简单.利用DWR可以在客户端利用JavaScript直接调用服务端的Java方法并返回值给 ...
- find、grep、sed、awk命令(总结)
find.grep.sed.awk命令(总结) 大纲 *一.常见系统特殊符号* *(一)基础符号系列* *1)美元符号 $* *2)叹号符号 !* *3)竖线符号 |* *4)井号符号 #* *(二) ...
- 深度观察2024中国系统架构师大会(SACC)
今年的中国系统架构师大会(SACC)在我所在的城市广州举办,很荣幸受邀参加.这次能接触到国内最优秀的架构师,学习他们的架构思想和行业经验.对我而言非常有意义. 大会分为上下午共4场,我参加了上午的多云 ...
- 三维模型3DTile格式轻量化压缩在移动智能终端应用方面的重要性分析
三维模型3DTile格式轻量化压缩在移动智能终端应用方面的重要性分析 随着移动智能终端设备的不断发展和普及,如智能手机.平板电脑等,以及5G网络技术的推广应用,使得在这些设备上频繁使用三维地理空间数据 ...
- 记录--记录用前端代替后端生成zip的过程,速度快了 57 倍!!!
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 业务场景: 产品有个功能是设置主题.类似手机自动切换壁纸,以及其他功能颜色,icon,字体等. 管理员需要在后端管理系统多次下载不同主题, ...
- 记录--纯CSS实现一个简单又不失优雅的步骤条
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 步骤条是一种用于引导用户按照特定流程完成任务的导航条,在各种分步表单交互场景中广泛应用.先来看一下几个主流前端 UI 框架中步骤条组件的样 ...