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的开发模式.本文将介绍依赖注入的基本概念,并 ...
随机推荐
- WEB入门——爆破21-28
WEB21 首先尝试网站后台常见登陆的弱口令,发现错误 则使用burp suite抓包试试看 通过分析,在未填入账号密码时,响应头如下所示: 填入弱口令账号密码,发现响应头如下: 则对应可知账号密 ...
- 【微服务架构设计实施】第一部分:架构篇-1:微服务架构与Spring Cloud介绍
〇.概述 一.微服务架构与Spring Cloud (一)概念 不同说法:细粒度的.清凉组件化的小型SOA(面向服务架构) 统一说法:小型应用程序(服务组件),使用轻量级设计方法和HTTP协议通信 理 ...
- 【每日一题】【比较中右,内部比较中右,注意边界带>=】2021年11月2日-搜索旋转排序数组-211102/220211
[某下标处进行了旋转]整数数组 nums 按升序排列,数组中的值 互不相同 . 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋 ...
- JavaScript入门⑦-DOM操作大全
JavaScript入门系列目录 JavaScript入门①-基础知识筑基 JavaScript入门②-函数(1)基础{浅出} JavaScript入门③-函数(2)原理{深入}执行上下文 JavaS ...
- Python Excel 处理模块 : OpenPyXL
OpenPyXL模块使用方法 以下是介绍OpenPyXL的基本使用,不涉及样式和合并单元格的跨行操作 一般来说,对于大名鼎鼎的xlrd,xlwt和xlutils三个模块,Excel操作有3个基本状态 ...
- SpringBoot基础学习笔记
Springboot框架: springboot官网参考 Sringboot是整合spring技术栈的一站式框架,其简化配置,实现了自动化配置 Springboot基础结构: 1.pom.xml文件: ...
- [编程基础] Python谷歌翻译库googletrans总结
1 使用说明 本文介绍python谷歌翻译库接口googletrans的使用.具体见官方文档: https://py-googletrans.readthedocs.io/en/latest/#goo ...
- 用云服务器搭建frp服务(超详细)
初学.没有云服务器的时候总想着怎样才能让别人访问到自己的项目. 在查阅了百度,逛过了一些论坛之后,了解到了 内网穿透 这个词. 经过一番钻研,通过 手机 + KSWEB + 电脑 成功将内网服务映射出 ...
- 【FAQ】推送服务常见问题及解决方案
一.推送成功收不到消息,推送返回:{"message":"success","requestID":"1523868*****28 ...
- 题解 P5607 [Ynoi2013] 无力回天 NOI2017
简要题意 其实我觉得这个部分可以不要,因为这道题的题面还是很清晰的. 你需要维护一个数据结构,支持区间异或和区间求与 \(v\) 的最大异或和. 思路 对于这种区间问题,最容易想到的就是 分块 线段树 ...