ASP.NET Core - 依赖注入(二)
- .NET Core 依赖注入的基本用法
话接上篇,这一章介绍 .NET Core 框架自带的轻量级 Ioc 容器下服务使用的一些知识点,大家可以先看看上一篇文章 [ASP.NET Core - 依赖注入(一)]
2.3 服务解析
通过 IServiceCollection 注册了服务之后,可以通过以下方式解析相应服务的实例:
- IServiceProvider
IServiceProiver 实例由 IServiceCollection 通过 BuildServiceProvider() 方法创建,在 ASP.NET Core 中,主机启动的时候会创建一个全局的 IServiceProvider,并且此实例也在容器当中。所有在容器注册过的服务都可以通过 IServiceProiver 进行解析,当然该服务的依赖项必须也在容器中注册。 - ActivatorUtilities
用于手动创建未在DI容器中注册的服务实例
2.3.1 服务注入方式
当我们通过容器解析一个服务实例的时候,容器根据当前服务的链式依赖关系图解析其依赖项,根据依赖项的生命周期或创建、或从已有的实例获取,然后注入到我们解析的服务当中。在一个服务中获取另一个服务实例的方式由以下几种:
(1) 构造函数注入
构造函数注入是非常常见的服务注入方式,也是微软最推荐的方式,这种方式可以明确地声明当前类所依赖的东西,一目了然。如同上面的示例代码中,使用的就是构造函数注入方式。构造函数注入,对于类的构造函数有以下要求:
构造函数可以接收非依赖注入的参数,但必须提供默认值
当服务通过 IServiceProvider 解析时,要求构造函数必须是 public
当服务由 ActivatorUtilities 解析时,构造函数注入要求只存在一个适用的构造函数。 支持构造函数重载,但其参数可以全部通过依赖注入来实现的重载只能存在一个。
如果发现构造函数时存在歧义,将引发异常,例如以下情况:
public class ExampleService
{
public ExampleService()
{
} public ExampleService(ILogger<ExampleService> logger)
{
// omitted for brevity
} public ExampleService(IOptions<ExampleOptions> options)
{
// omitted for brevity
}
}
(2) 属性注入
这里有一点需要说明,.NET Core 内置的依赖注入框架并不支持属性注入,如果需要使用属性注入需要结合第三方依赖注入框架进行使用,如autofac。
顾名思义,属性注入就是通过类中的属性注入需要的服务,要求属性必须是 public ,并且具备 get、set 访问器。如下:
属性注入一般用于注入一些即使缺失了也不会导致当前类无法工作的依赖项,如日志记录等。这种时候会为数据注入设置一个默认实现,防止该属性为空,导致当前类的功能受影响。
(3) 方法注入
通过 FromServicesAttribute 特性在控制器的方法参数中注入,这种方式只能用于控制器。默认情况下,控制器示例由容器来管理,在入口文件调用 builder.Services.AddControllers(); 时注册到容器中。
[HttpGet(nameof(InjectTest3))]
public Task InjectTest3([FromServices] IRabbit rabbit)
{
Console.WriteLine(rabbit is Rabbit);
return Task.CompletedTask;
}
这种方式用于缩小依赖注入的粒度,适用于注入的服务只在当前方法使用的时候,是对构造函数注入的简化。
(4) 手动解析
在.NET框架中,任何可以拿得到 IServiceProvider 实例的地方都可以通过 GetRequiredService() 或者 GetService() 解析我们需要的服务。直接使用 IServiceProvider 是服务定位器模式的一个示例。这通常被认为是反模式,因为它隐藏了类的依赖关系。这种方式在某些情况下是有用的,但是应该尽量避免。
GetService() 与 GetRequiredService() 的区别在于解析服务时,如果该服务没有在容器中注册,前者会返回Null,而后者会抛出异常。两者的区别可参考以下文件:ASP.NET Core中GetService()和GetRequiredService()之间的区别
除了通过注入 IServiceProvider 来解析服务之外,其他的方式,例如 HttpContext 中也包含 IServiceProvider 实例,如:
var rabbit1 = HttpContext.RequestServices.GetRequiredService<IRabbit>();
2.3.2 ActivatorUtilities 使用
通过 ActivatorUtilities 解析服务比较简单,常用的由以下两个方法:
ActivatorUtilities.CreateInstance<HelloService>(provider, "test");
ActivatorUtilities.GetServiceOrCreateInstance<IHelloService>(provider);
其中 CreateInstance 方法的泛型类型需要是具体的类型,而不是接口,这个方法还可以传入构造函数需要的,但没有在容器中注册的参数。GetServiceOrCreateInstance 方法会先尝试从容器获取实例,获取不到再创建,不支持不在容器中注册的构造函数参数。
参考文章:
ASP.NET Core 依赖注入 | Microsoft Learn
理解ASP.NET Core - 依赖注入(Dependency Injection)
ASP.NET Core 系列:
目录:ASP.NET Core 系列总结
上一篇:ASP.NET Core - 依赖注入(一)
ASP.NET Core - 依赖注入(二)的更多相关文章
- 实现BUG自动检测 - ASP.NET Core依赖注入
我个人比较懒,能自动做的事绝不手动做,最近在用ASP.NET Core写一个项目,过程中会积累一些方便的工具类或框架,分享出来欢迎大家点评. 如果以后有时间的话,我打算写一个系列的[实现BUG自动检测 ...
- asp.net core 依赖注入几种常见情况
先读一篇注入入门 全面理解 ASP.NET Core 依赖注入, 学习一下基本使用 然后学习一招, 不使用接口规范, 直接写功能类, 一般情况下可以用来做单例. 参考https://www.cnblo ...
- ASP.NET Core依赖注入——依赖注入最佳实践
在这篇文章中,我们将深入研究.NET Core和ASP.NET Core MVC中的依赖注入,将介绍几乎所有可能的选项,依赖注入是ASP.Net Core的核心,我将分享在ASP.Net Core应用 ...
- 自动化CodeReview - ASP.NET Core依赖注入
自动化CodeReview系列目录 自动化CodeReview - ASP.NET Core依赖注入 自动化CodeReview - ASP.NET Core请求参数验证 我个人比较懒,能自动做的事绝 ...
- # ASP.NET Core依赖注入解读&使用Autofac替代实现
标签: 依赖注入 Autofac ASPNETCore ASP.NET Core依赖注入解读&使用Autofac替代实现 1. 前言 2. ASP.NET Core 中的DI方式 3. Aut ...
- [译]ASP.NET Core依赖注入深入讨论
原文链接:ASP.NET Core Dependency Injection Deep Dive - Joonas W's blog 这篇文章我们来深入探讨ASP.NET Core.MVC Core中 ...
- ASP.NET Core 依赖注入最佳实践——提示与技巧
在这篇文章,我将分享一些在ASP.NET Core程序中使用依赖注入的个人经验和建议.这些原则背后的动机如下: 高效地设计服务和它们的依赖. 预防多线程问题. 预防内存泄漏. 预防潜在的BUG. 这篇 ...
- ASP.NET Core依赖注入最佳实践,提示&技巧
分享翻译一篇Abp框架作者(Halil İbrahim Kalkan)关于ASP.NET Core依赖注入的博文. 在本文中,我将分享我在ASP.NET Core应用程序中使用依赖注入的经验和建议. ...
- ASP.NET Core依赖注入解读&使用Autofac替代实现【转载】
ASP.NET Core依赖注入解读&使用Autofac替代实现 1. 前言 2. ASP.NET Core 中的DI方式 3. Autofac实现和自定义实现扩展方法 3.1 安装Autof ...
- ASP.NET Core 依赖注入基本用法
ASP.NET Core 依赖注入 ASP.NET Core从框架层对依赖注入提供支持.也就是说,如果你不了解依赖注入,将很难适应 ASP.NET Core的开发模式.本文将介绍依赖注入的基本概念,并 ...
随机推荐
- day25-Listener监听器
Listener监听器 1.Listener监听器介绍 Listener监听器是JavaWeb三大组件之一.JavaWeb三大组件分别是:Servlet程序,Listener监听器,Filter过滤器 ...
- PLSql在Oracle中创建表空间
create tablespace db_test --表空间名 datafile 'D:\oracle\product\11.2.0\dbhome_1\oradata\orcl\test.dbf' ...
- Zabbix技术分享——使用Zabbix6.0监控业务日志
企业日常IT运维过程中,常会碰到需要监控业务日志的情况,以下将介绍如何使用Zabbix6.0监控业务日志. 应用场景描述: 企业IT运维部门使用自建zabbix平台对公司某业务系统进行了监控.近段时间 ...
- 数据结构高阶--AVL(平衡二叉树)(图解+实现)
AVL树(平衡二叉树) 概念 二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下.因此为了解决这个问题,两位俄罗斯的数学家发明 ...
- 【Hadoop学习】中:HDFS、shell操作、客户端API操作、数据流、1NN、2NN原理、DataNode配置
一.概述 1.背景.定义.使用场景(一次写入.不支持修改) 2.优(容错)缺点(延迟.不支持小文件.不支持修改) 3.组成架构 NameNode:Master,管理命名空间.配置策略 DataNode ...
- Day34.2:Calendar详解
Calendar 1.1 概述 Date类中很多方法被Calendar所取代,Calendar类提供了获取和设置各种日历的方法. 1.2 方法 构造方法:Calendar类的构造器被protected ...
- 一文速览 Dubbo 3.0
本文将带你快速了解 Dubbo3 的设计背景.总体架构与核心特性.与典型用户如阿里巴巴 HSF2 的关系等.也可以通过如下部分了解更多: 小白用户,快速浏览 Dubbo3 核心特性: 下一代通信协议 ...
- Jenkins&&gitlab
DevOps 强调整个组织的合作以及交付和基础设施变更的自动化 gitlab下载: 下载地址: https://docs.gitlab.com/ee/install/requirements.html ...
- java顺序数组插入元素
本文主要阐明已知顺序数组,在数组中插入一个数据元素,使其仍然保持有序. 关键是寻找num在原数组中插入的位置: 当num在原数组中是最大的情况,num应该插入到原数组的末尾. 否则,应该遍历原数组,通 ...
- Jmeter 之提取多个值并引用
一.数值的提取 1.使用Json提取器随机提取返回结果中某几个值 2.使用Json提取器指定提取返回结果中的某几个值,如下,指定提取records中第一条数据中的flowType.id值 3.使用正则 ...