ASP.NET Core技术研究-探秘依赖注入框架

news/2025/1/5 17:12:10/文章来源:https://www.cnblogs.com/lgx5/p/18644349

ASP.NET Core在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务、提供服务。依赖注入不仅服务于ASP.NET Core自身,同时也是应用程序的服务提供者。

毫不夸张的说,ASP.NET Core通过依赖注入实现了各种服务对象的注册和创建,同时也实现了面向抽象的编程模式和编程体验,提升了应用程序的扩展性。

今天,我们普及一下ASP.NET Core中依赖注入的一些基本知识。

一、服务的注册

   我们通过创建一个ASP.NET Core的项目,可以发现在Startup.cs 类中,有一个方法ConfigureServices,这个方法的注释是这样的:

     This method gets called by the runtime. Use this method to add services to the container.

   

  在ConfigureServices方法中我们可以将通过ASP.NET Core内置的依赖注入框架实现服务的的注册。

  这个方法有个参数:IServiceCollection,见名知意,服务集合。

  ASP.NET Core内置的依赖注入框架将服务注册信息存储到一个实现了IServiceCollection接口的对象中。默认情况下这个接口的实现类是ServiceCollection,以下是这个类的说明:

  https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicecollection?view=dotnet-plat-ext-3.1

  通过这个接口和类实现,我们可以发现,注册服务其实就是将一个服务的ServiceDescriptor对象添加到ServiceCollection集合中。

  例如:

public void ConfigureServices(IServiceCollection services)
{services.Add(new ServiceDescriptor(typeof(IUserRepository), new UserRepository()));services.AddControllers();
}

 ServiceDescriptor可以理解为对某个服务注册项的描述。ASP.NET Core的依赖注入容器IServiceProvider通过ServiceDescriptor的信息,动态创建服务的实例Instance. 

   我们看一下这个ServiceDescriptor类:

   

   有几个关键的属性:

     1. ServiceType:服务的类型,例如服务接口的类型信息

     2. ImplementationType:服务的实现类型,例如服务接口实现类的类型信息

     3. ImplementationInstance:实现服务的实例,一般是服务单例模式场景下使用。 https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.servicedescriptor.-ctor?view=dotnet-plat-ext-3.1#Microsoft_Extensions_DependencyInjection_ServiceDescriptor__ctor_System_Type_System_Object_

    4. Lifetime:服务生命周期:Scoped(同一个请求中同一个IServiceProvider提供的对象是同一个)、Singleton(单例)、Transient(每次从服务容器进行请求时创建)

    5. ImplementationFactory 服务实例创建工厂,自定义的IServiceProvider服务提供容器

  服务注册提供了一系列重载的方法,大家可以根据需要进行选择:

  

     服务注册的过程中,涉及到了服务的生命周期的概念,接下来我们详细看一下。

二、服务生命周期

   服务的生命周期设置,决定了服务提供容器IServiceProvider使用什么样的方式提供服务实例对象。正如上面第一章节所说的,

   ASP.NET Core服务依赖注入框架,支持三种类型的服务生命周期:

  •    Singleton
  •    Scoped
  •    Transient

  其中:

   Transient:暂时的,每次从服务容器进行请求时创建。 这种生存期适合轻量级、 无状态的服务。

   Singleton:单一实例,在第一次请求时(或者在运行 Startup.ConfigureServices 并且使用服务注册指定实例时)创建的。每个后续请求都使用相同的实例。

   Scoped:范围内的,作用域生存期服务,以每个客户端请求(连接)一次的方式创建。可以这么理解:同一个请求中同一个IServiceProvider提供的对象是同一个。

   微软给了个例子不错:先注册服务,三种类型

public void ConfigureServices(IServiceCollection services)
{    <br>    services.AddRazorPages(); <br>    services.AddScoped<IMyDependency, MyDependency>();services.AddTransient<IOperationTransient, Operation>();services.AddScoped<IOperationScoped, Operation>();services.AddSingleton<IOperationSingleton, Operation>();services.AddSingleton<IOperationSingletonInstance>(new Operation(Guid.Empty));//OperationService depends on each of the other Operation types.services.AddTransient<OperationService, OperationService>();
}

第一个请求:   

控制器操作:
暂时性:d233e165-f417-469b-a866-1cf1935d2518
作用域:5d997e2d-55f5-4a64-8388-51c4e3a1ad19
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000OperationService 操作:
暂时性:c6b049eb-1318-4e31-90f1-eb2dd849ff64
作用域:5d997e2d-55f5-4a64-8388-51c4e3a1ad19
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000

第二个请求:

第二个请求:
控制器操作:
暂时性:b63bd538-0a37-4ff1-90ba-081c5138dda0
作用域:31e820c5-4834-4d22-83fc-a60118acb9f4
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000OperationService 操作:
暂时性:c4cbacb8-36a2-436d-81c8-8c1b78808aaf
作用域:31e820c5-4834-4d22-83fc-a60118acb9f4
单一实例:01271bc1-9e31-48e7-8f7c-7261b040ded9
实例:00000000-0000-0000-0000-000000000000

大家可以根据实际的需要选择服务的生命周期,创建不同类型的服务。

三、服务的消费

  前面,我们将服务注册到IServiceCollection,ASP.NET Core服务提供容器IServiceProvider就可以根据IServiceCollection 创建具体类型的服务对象了。

  我们先看一下IServiceProvider接口,可以发现:只有一个GetService方法。

  

 

  我们可以通过以下代码使用:

public static void Main(string[] args)
{var builder = CreateHostBuilder(args);           var host = builder.Build();var userRepo = host.Services.GetService(typeof(IUserRepository)) as IUserRepository;userRepo.AddUser("user");host.Run();
}

同时,我们更多常用的是:

 将服务通过ASP.NET Core依赖注入框架注入到控制器中

 ASP.NET Core MVC 控制器通过构造函数显式请求依赖关系。即:通过构造函数注入服务的实现。

 前面,我们通过ConfigureServices注册了服务IUserRepository,在Controller这一层如何消费使用这个服务呢?答案就是在Controller构造函数中注入。

 看一段示例代码:(HomeController的构造函数中,增加了一个参数IUserRepository)

public class HomeController : Controller{private readonly ILogger<HomeController> _logger;    private IUserRepository _userRepository;public HomeController(ILogger<HomeController> logger, IUserRepository userRepository){_logger = logger;_userRepository = userRepository;}public IActionResult Index(){_userRepository.AddUser(new User() {  });return View();}public IActionResult Privacy(){return View();}[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]public IActionResult Error(){return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });}}

同时,ASP.NET Core MVC 控制器支持通过注解FromServicesAttribute, 将服务直接注入到Action方法中,而无需使用构造函数注入:

public IActionResult Index([FromServices] IUserRepository userRepository)
{userRepository.AddUser(new User() {  });return View();
}

ASP.NET Core除了支持将服务注入到控制器,同时还支持将服务依赖注入到视图,可以参考以下链接:

    https://docs.microsoft.com/zh-cn/aspnet/core/mvc/views/dependency-injection?view=aspnetcore-3.0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/861963.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

读懂华为开发者空间第一课,让云上开发如此简单

课程由浅入深带领开发者了解华为开发者空间,包含鲲鹏、昇腾、鸿蒙等华为优质开发工具和资源、真实项目开发案例等,构建对华为开发者空间的系统性认知框架。近日,华为云上线的《华为开发者空间快速入门》课程,汇聚了理论知识讲解、案例介绍和丰富的实践练习,通过循序渐进的…

【iscsi使用】3.无盘启动CentOS7

目录1.SAN存储及NAS存储 2.CentOS7搭建iscsi服务器 3.无盘启动CentOS7前言业务中遇到这样一个问题: 使用别人的GPU服务器,来跑自己的训练数据。 因为数据的特殊性,一旦数据落盘到GPU服务器,硬盘必须交给数据方。数据方也提出,可提供同型号同容量的硬盘更换。但是机器方考虑…

.NET Core技术研究-HttpContext访问的正确方式

将ASP.NET升级到ASP.NET Core之后,相信大家都会遇到HttpContext.Current无法使用的问题。这也是我们迁移ASP.NET Core必须解决的问题。 先列一下使用HttpContext的具体场景: 1. 在Controller层访问HttpContext 2. 在中间件中使用HttpContext 3. 在数据访问层使用HttpContext …

chrome播放webRTC的H265视频方法

需求描述 最近有需求实现浏览器直接播放摄像头视频 鉴于Camera本身支持了rtsp流,本想web直接播放rtsp,但是还不行,搜了一下webRTC实现的效果和延迟会好一些。于是就使用了mediaMTX转了下rtsp的流,变为webRTC。 随便写了个h5页面对视频进行播放,使用下面代码的话替换一下sr…

在Excel 2013中调出开发工具

打开Excel 2013,点击左上角的【文件】菜单,在【文件】菜单下,选择【选项】按钮 在弹出的【Excel选项】界面中,选择【快速访问工具栏】。在【自定义功能区】处,勾选【开发工具】选项。设置完成后,关闭【选项】界面。这时,在功能区靠右端就可以看到新增加的【开发工具】选…

库卡机械臂驱动器KPS600故障维修

首先,当出现库卡机器人驱动器过载时,首要任务是确认过载的原因。过载可能由多种因素引起,如电源电压不稳定、负载过大、电机故障或控制器设置不当等。通过检查电源电压、负载情况、电机运行状态以及控制器设置,我们可以初步判断KUKA工业机械手驱动器过载的根源。 一旦确定了…

流量分析 - 练习篇2

L1-2 流量分析流量包描述:某天晚上安服仔小辉辉上班摸鱼期间突然发现服务器登入页面被挤掉线了,于是第六感告诉他,服务器肯定是被黑客攻击了,于是他赶紧把服务器的网线拔了并调取了那段时间的流量,然后慌忙的找到你,求求你救救安服仔吧1.分析L1-2.pcapng数据包文件,通过…

Centos 7.9部署ldap 2.4.44

1、环境准备 [root@ldap81 openldap]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [root@ldap81 openldap]# uname -r 3.10.0-1160.119.1.el7.x86_64systemctl stop firewalld systemctl disable firewalld setenforce 0 hostnamectl set-hostname ldap81…

[241231]阿普米司特抗银屑病的同时辅助抗真菌感染

已知真菌定植/感染可能参与触发或加重斑块状银屑病. 抗IL-17和TNFi可能增加真菌感染风险. 一项探索性研究通过70例难治部位(头皮, 指甲, 间擦部/外生殖器)银屑病患者接受阿普米司特治疗前以及治疗1年过程中(允许局部真菌感染入组并继续抗真菌治疗), 监测真菌定植/局部真菌感染以…

为什么企业需要 IT 资产管理软件?

当前企业的运营越来越依赖于信息技术,从日常办公的电脑、打印机到支撑核心业务的服务器、网络设备等,IT 资产已经成为企业不可或缺的重要组成部分。而 IT 资产管理软件在这个过程中发挥着至关重要的作用。 企业面临的 IT 资产管理问题 1、资产数量庞大且种类繁多 随着企业的…

delphi 协程 doroutine bg + ui 嵌套 并行

前言 bg 与 ui 是互相嵌套的,没有终点;就是说 程序 若是高密计算,ui + bg 一切同时并行,快速响应; 示例代码 unit main;interfaceusesWinapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,Vcl.Controls, Vcl.Forms, Vcl.D…