当前位置: 首页 > news >正文

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

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

    以上是对ASP.NET Core依赖注入框架的研究,分享给大家。

往期精彩回顾

  • 【.net core】电商平台升级之微服务架构应用实战

  • .Net Core微服务架构技术栈的那些事

  • Asp.Net Core 中IdentityServer4 授权中心之应用实战

  • Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式

  • Asp.Net Core 中IdentityServer4 授权流程及刷新Token

  • Asp.Net Core 中IdentityServer4 实战之 Claim详解

  • Asp.Net Core 中IdentityServer4 实战之角色授权详解

  • Asp.Net Core 中间件应用实战中你不知道的那些事

  • Asp.Net Core Filter 深入浅出的那些事-AOP

  • Asp.Net Core EndPoint 终结点路由工作原理解读

  • ASP.NET CORE 内置的IOC解读及使用


http://www.taodudu.cc/news/show-911417.html

相关文章:

  • 纯血鸿蒙APP实战开发——一镜到底“页面转场”动画
  • QMetaObject 是 Qt 框架中的一个重要类,用于在运行时处理对象的元对象信息
  • 虚拟数字人及AI相关应用分享
  • Shell函数
  • 序列化的不同格式:JSON、XML、TOML、CSON、YAML
  • Docker运行出现iptables: No chain/target/match by that name报错如何解决?
  • 从项目到产品: 软件时代需要价值流架构师 | IDCF
  • 推荐一个集录屏、截图、音频于一体的软件给大家
  • WebAssembly增加Go语言绑定
  • .NET中的内存管理
  • .Net微服务实战之技术架构分层篇
  • .NET 下基于动态代理的 AOP 框架实现揭秘
  • Blazor WebAssembly 3.2.0 Preview 4 如期发布
  • C#/.Net Core/WPF框架初建(国际化、主题色)
  • ASP.NET Core 日志框架:Serilog
  • 树莓派销量突然猛增
  • C#黔驴技巧之实现统计结果排名
  • Istio Pilot架构解析
  • 当模板方法遇到了委托函数,你的代码又可以精简了
  • 为什么要用内插字符串代替string.format
  • iPhone上运行Linux也要来了
  • 谁说.NET不适合搞大数据、机器学习和人工智能
  • .NET Core技术研究-主机
  • 多角度让你彻底明白yield语法糖的用法和原理及在C#函数式编程中的作用
  • 哪种开源许可证最适合商业化?
  • 还不会docker+k8s?2020年,就要面对现实了...
  • 3分钟掌握Quartz.net分布式定时任务的姿势
  • ASP.NET Core 配置源:实时生效
  • Linq下有一个非常实用的SelectMany方法,很多人却不会用
  • .NET Core前后端分离快速开发框架(Core.3.1+AntdVue)
  • 如何选择好公司
  • 同步异步多线程这三者关系,你能给面试官一个满意的回答吗?
  • [一起读源码]走进C#并发队列ConcurrentQueue的内部世界 — .NET Core篇
  • EFCore.Sharding(EFCore开源分表框架)
  • k8s中流量分离以及资源隔离实战
  • 怎样实现WPF Prism Module的国际化和本地化?