首页 > 其他分享 >.Net Core 依赖注入DI

.Net Core 依赖注入DI

时间:2024-03-13 11:45:25浏览次数:18  
标签:Core 依赖 服务 DI 作用域 ServiceProvider 实例 Scoped Net

一、依赖注入 (DI) 定义

      依赖注入(Dependency Injection,简称DI)是一种设计模式,用于解耦组件(服务)之间的依赖关系。它通过将依赖关系的创建和管理交给外部容器来实现,而不是在组件(服务)内部直接创建依赖对象。

      它可以帮助我们更好地管理和组织组件,提高代码的可读性,扩展性和可测试性。

​      通过 IServiceCollection 和 IServiceProvider 来实现的,他们直接被收入到了runtime libraries,在整个.NET平台下通用。

      ServiceProvider: 

      ServiceProvider(依赖注入容器)不仅对外提供GetService()、GetRequiredService()方法,还可以方便地注册和管理应用程序需要的各种服务。
      通过创建ServiceProvider的方式,我们可以更好地理解管理和控制服务实例的生命周期和依赖关系。

  1. 应用程序级别的根级ServiceProvider
    .NET Core应用程序通常会使用一个应用程序级别的根级ServiceProvider,它是全局唯一的,并且负责维护所有单例服务的实例。这个实例通常是由WebHostBuilder、HostBuilder或ServiceCollection等类创建和配置的,可以通过IServiceProvider接口来访问。

  2. 每个请求的作用域级别的ServiceProvider
    除了根级ServiceProvider之外,在.NET Core中还可以创建每个请求的作用域级别的ServiceProvider,它通常用于管理Scoped和Transient服务的生命周期和依赖关系。每个作用域级别的ServiceProvider都有自己独立的作用域,可以通过IServiceScopeFactory创建,同时也继承了根级ServiceProvider中注册的所有单例服务的实例。

  3. 自定义级别的ServiceProvider
    在某些情况下,我们可能需要自定义级别的ServiceProvider来满足特定的业务需求,例如,将多个ServiceProvider组合起来以提供更高级别的服务解析和管理功能。此时,我们可以通过实现IServiceProviderFactory接口和IServiceProviderBuilder接口来创建和配置自定义级别的ServiceProvider,从而实现更灵活、可扩展的依赖注入框架。    

          重要对象

    • IServiceCollection: 用于注册应用程序所需的服务实例,并将其添加到依赖注入容器中。

    • IServiceScopeFactory: 用于创建依赖注入作用域(IServiceScope)的工厂类。每个IServiceScope都可以独立地管理Scoped和Transient类型的服务实例,并在作用域结束时释放所有资源。IServiceScope通过ServiceProvider属性来访问该作用域内的服务实例

    • ServiceProvider: 可以看作是一个服务容器,它可以方便地注册、提供和管理应用程序需要的各种服务。还支持创建依赖注入作用域(IServiceScope),可以更好地管理和控制服务实例的生命周期和依赖关系

    • IServiceProviderFactory: 创建最终的依赖注入容器(IServiceProvider),提供默认的DefaultServiceProviderFactory(也就是官方自带的IOC),也支持自定义的,比如autofac的AutofacServiceProviderFactory工厂。

    • ServiceProviderEngineScope: 实现了IServiceProvider和IDisposable接口,用于创建和管理依赖注入作用域(Scope)。通过使用ServiceProviderEngineScope,我们可以访问依赖注入作用域中的服务实例,并实现Scoped和Transient类型的服务实例的生命周期管理。作用域机制可以帮助我们更好地管理和控制应用程序的各个组件之间的依赖关系

    • CallSiteFactory: 通常由依赖注入容器(如ServiceProvider)在服务解析过程中使用。当容器需要解析某个服务时,它会创建一个CallSiteFactory对象,并使用其中的静态方法来创建对应的ServiceCallSite对象。然后,容器会将这些ServiceCallSite对象组合成一个树形结构,最终构建出整个服务实例的解析树。

    • ServiceCallSite: 表示服务的解析过程。它包含了服务类型、服务的生命周期、以及从容器中获取服务实例的方法等信息

    • CallSiteVisitor: 通常由依赖注入容器(如ServiceProvider)在服务解析过程中使用。当容器需要解析某个服务时,它会创建一个ServiceCallSite的对象图,并将其传递给CallSiteVisitor进行遍历和访问。CallSiteVisitor通过调用不同节点的虚拟方法,将每个节点的信息收集起来,并最终构建出服务实例的解析树。

    • CallSiteValidator 通常由依赖注入容器(如ServiceProvider)在服务解析过程中使用,用于验证ServiceCallSite对象图的正确性。它提供了一组检查方法,可以检测ServiceCallSite对象图中可能存在的循环依赖、未注册的服务类型和生命周期问题等。

二、依赖注入三个生命周期:

       我们可以将依赖注入容器看作一个树形结构,其中root节点的子节点是Scoped节点,每个Scoped节点的子节点是Transient节点(如果存在)。在容器初始化时,会在root节点下创建和缓存所有单例服务的实例,以及创建第一个Scoped节点。

       每个Scoped节点下都有一个独立的作用域,用于管理Scoped服务的生命周期和依赖关系,同时还继承了父级节点(即root或其他Scoped节点)的所有单例服务的实例。 在处理每个新的请求时,依赖注入容器会创建一个新的Scoped节点,

        并在该节点下创建和缓存该请求所需的所有Scoped服务的实例。在完成请求处理后,该Scoped节点及其下属的服务实例也将被销毁,从而确保Scoped服务实例的生命周期与请求的作用域相对应。

  1)暂时(Transient)
    暂时生存期服务是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。
       2)作用域(Scoped)
            对于 Web 应用,指定了作用域的生存期指明了每个客户端请求(连接)创建一次服务。在处理请求的应用中,在请求结束时会释放有作用域的服务。

            使用 Entity Framework Core 时,默认情况下使用范围内生存期来注册 DbContext 类型。
       3)单例(Singleton)
            来自依赖关系注入容器的服务实现的每一个后续请求都使用同一个实例。 如果应用需要单一实例行为,则允许服务容器管理服务的生存期。

            单一实例服务必须是线程安全的,并且通常在无状态服务中使用。如处理文件时候应用单例注册。
            注意:不要从单一实例解析限定范围的服务,并小心不要间接地这样做,例如通过暂时性服务。 当处理后续请求时,它可能会导致服务处于不正确的状态。最直接的影响是限定范围的服务无法释放,间接成了单例模式。

                      一定要使用,就自己创建,并且显式管理它的生命周期。

 三、依赖注入要掌握的知识点(老张的哲学

        

 

     参考来源:https://www.cnblogs.com/ysmc/p/16012269.html

                       https://www.cnblogs.com/xiaolipro/p/17873575.html

                      https://www.cnblogs.com/Z7TS/p/17402544.html

 

标签:Core,依赖,服务,DI,作用域,ServiceProvider,实例,Scoped,Net
From: https://www.cnblogs.com/fyshao/p/18070220

相关文章

  • 开源.NET 全能 Cron 表达式解析库(支持 Cron 所有特性)
    前言今天大姚给大家分享一个.NET全能Cron表达式解析类库,支持Cron所有特性:TimeCrontab。Cron表达式介绍Cron表达式是一种用于配置定时任务的时间表达式。它由一系列字段组成,每个字段代表任务在不同时间维度的调度规则。Cron表达式常用于各种系统中,如操作系统的定时任务、......
  • 【Paper Reading】7.DiT(VAE+ViT+DDPM) Sora的base论文
    VAEDDPM 分类内容论文题目ScalableDiffusionModelswithTransformers作者WilliamPeebles(UCBerkeley),SainingXie(NewYorkUniversity)发表年份2023摘要介绍了一类新的扩散模型,这些模型利用Transformer架构,专注于图像生成的潜在扩散模型。这些......
  • 开源.NET8.0小项目伪微服务框架(分布式、EFCore、Redis、RabbitMQ、Mysql等)
    1、前言为什么说是伪微服务框架,常见微服务框架可能还包括服务容错、服务间的通信、服务追踪和监控、服务注册和发现等等,而我这里为了在使用中的更简单,将很多东西进行了简化或者省略了。年前到现在在开发一个新的小项目,刚好项目最初的很多功能是比较通用的,所以就想着将这些功能......
  • SqlServer函数大全三十五:DATEDIFF(返回日期和时间的边界数)函数
    在SQLServer中,DATEDIFF 函数用于返回两个日期之间的边界数差异。这个函数可以计算两个日期之间的年、月、日、小时、分钟、秒或周数差异。DATEDIFF 函数的语法如下:sql复制代码DATEDIFF(datepart,startdate,enddate)datepart 是指定要返回日期部分的参数,比如......
  • 39_配置redis集群
    配置redis集群三主三从集群设置Master1(6381)Master2(6382)Master3(6383)Slave1(6384)Slave2(6385)Slave3(6386)拉取镜像启动容器dockerpullredis:6.0.8dockerrun-d--nameredis-node-1--nethost--privileged=true-v/dataredis:6.0.8--cluster-en......
  • Assetbundle.Unload(true)卸载资源时没调用ScriptableObject的OnDisable
    1)Assetbundle.Unload(true)卸载资源时没调用ScriptableObject的OnDisable2)UnityVolumeManager中ReplaceData如何优化3)关于使用Addressable的资源放在远程服务器后的下载问题4)Prefab对DLL中脚本的引用丢失这是第377篇UWA技术知识分享的推送,精选了UWA社区的热门话题,涵盖了UWA问答......
  • aardio 背景透明的3种方式(透明窗体1 webview2,透明窗体2-win-region-bitmap,透明窗体3-w
    3种透明模式我给起个名字,也好记忆。透明模式1:浏览器模式透明模式2:位图遮罩模式透明模式3:背景透明模式aardio背景透明的3种方式(透明窗体1webview2,透明窗体2-win-region-bitmap,透明窗体3-winform-transparent-color)3种透明窗体,主要分成是否可以穿透,遮罩组件,全部显示。透明......
  • 数据库基础--Redis知识体系(掌握Redis,看完这篇文章就够了!)
    1.Redis数据库Redis是一个开源的高性能键值存储数据库,类似字典。通常用作缓存、消息队列和数据存储等用途。mysql,mongodb都是以文件形式存储在磁盘上的,redis数据存在内存中,操作内存的速度远远高于磁盘,并且redis数据最终也可以存储在磁盘上。Redis支持多种数据结构,包括字符串......
  • sharding-jdbc原理
    分片流程一、sql解析从3.0.x版本开始,ShardingSphere统一将SQL解析器换成了基于antlr4实现,目的是为了更方便、更完整的支持SQL,例如对于复杂的表达式、递归、子查询等语句,因为后期ShardingSphere的定位已不仅仅是数据分片功能。抽象语法树根据不同数据库方言所提供的字......
  • mac redis启动,redis哨兵模式,redis集群的相关命令
    Homebrew安装的软件会默认在/usr/local/Cellar/路径下redis的配置文件redis.conf存放在/usr/local/etc路径下cd/usr/local/Cellar/redis/7.0.10.存在cd/usr/local/opt/redis/bin/redis-server.目录存在cd/usr/local/etc/redis.conf存在。配置文件复制文件cp/us......