Asp.net core自定义依赖注入容器,替换自带容器
依赖注入
在asp.net core程序中,众所周知,依赖注入基本上贯穿了整个项目,以通用的结构来讲解,控制器层(Controller层)依赖业务层(Service层),业务层依赖于仓储层(Repository层),而其他层级中也或多或少的使用了依赖注入,在这里不过多的对于依赖注入概念上不进行讲解,如果有不了解的同学,可以在微软官网或者在搜索引擎搜索依赖注入相关概念,本文主要讲解如何在asp.net core中实现自己的依赖注入容器,并且希望更多的同学能够去阅读源码码,因为源码中暴露的一些抽象类或者接口向开发者提供了方便开发者自定义或者拓展的口子。好了,不多啰嗦,我们开始。
First IServiceProviderFactory接口
用过Autofac的同学都知道在asp.net core3版本之后,Autofac的使用方式稍微发生了一些变化,首先需要在Program.cs文件中需要使用Host.UseServiceProviderFactory方法,那实际上这个方法就是让开发者能够去实现自定义的依赖注入容器的一个拓展方法,我们可以查看一下这个方法的定义,注意看有个重点的接口就是IServiceProviderFactory接口,这个接口实际上是指定服务提供者的一个抽象工厂泛型接口,这是实现自定义IOC中最重要的接口之一,也是最开始的一步,实际上,实现自定义依赖注入容器,只需要实现两个接口就可以实现自定义容器,可以看到这个方法有两种参数机制一种是直接传入对应的 实现类,另一种是使用委托的方式去创建对象,并且传入了一个HostBuilderContext的对象,我们会使用这种方式去实现。
Second IServiceProvider接口
我们可以看到这个IServiceProviderFactory接口有两个实现方法,一个是CreateBuilder方法,里面传入IServiceCollection变量,另一个方法是CreateServiceProvider方法,传入我们这个接口指定的容器类的对象,其中IocContainer类不依赖于任何一个抽象,第一个方法的作用就是去构造这个容器的对象,需要返回我们指定的类型的对象,即是这个类是代表着容器,存放服务的,第二个方法是将上面构造的容器对象传入进来,并且返回我们指定的服务提供者,那概念很清晰了,第一个IServiceProviderFactory接口是用来指定我们的容器是哪一个类是我们的容器,以及哪一个是我们的服务提供者,那实际上的IServiceProvider就是第二个重要的一个接口了,这个接口是只有一个方法,GetService方法,参数是一个Type,代表着我们是要去获取哪一个类型的参数,返回值是Object,返回下层依赖者所需要的具体的一个对象。
Three 遵循规则实现自定义容器
那实际上自带的依赖注入容器也是遵循这种规则去实现的,它提供了一个自带的一个ServiceProvider的类去创建对象,那大家都知道启动一个Core的一个程序,自带的一些依赖对象都有一百多个,那大家可能会觉得,让自己去写这种一百多个对象的创建,并且类别还是core的开发者所没有暴露出的类型,创建起来会很麻烦,并且还存在各种依赖,让大家觉得可能自定义依赖注入容器可能很难,实际上,刚开始的时候我也是这么想的,表达式树在我去年十二月份的时候就开始写代码了,只是今年才上传到博客,那实际上,自定义容器我也是去年开始研究的,刚开始也是写了很多判断因为它内部启动的时候大的依赖了两个东西一个是配置的IConfiguration,还有一个就是一个Host的一个类,下面又依赖了很多很多的类,感觉创建起来很麻烦,后来在想到了反射是可以获取程序运行时的元数据并且去构造某个类型,那实际上,我们是可以用反射去实现一种投机取巧的方式去实现自定义依赖注入容器,那就是将启动所依赖服务由自带的ServiceProvider去进行提供和创建,一些项目开发中使用的服务由我们去进行管理,那说到这,已经有很多同学知道了怎么去进行了,我们看代码。
上图中,我们可以看到Provider类是实现了IServiceProvider的接口,并且实现了GetService的方法,可以看到,我使用的方式是去用反射去获取自带的ServiceProvider的构造函数,然后创建这个对象,并且在GetService方法中,首先去判断能否从自带的Provider去获取和创建对象,如果获取不到,那说明是我们项目中所需要的类型,从而使用我们自定义的容器去进行获取对象,默认的获取不到是因为我们在创建ServiceProvider对象的时候传入了IServiceCollection的对象,这里所包含的就是启动Core程序所需要的依赖的集合,这样我们就可以保证,程序启动的时候是可以正常启动的,然后在运行中,请求中所需要的服务类型是由我们自己去创建对象的,所以这样就实现了简单的IOC依赖注入容器,并且替换掉自带的容器。
Four 控制器层的属性注入以及拓展容器实现属性注入和一接口多实现
按照我文章刚开始的时候所说,微软给我们暴露了很多供我们自定义的接口和 抽象类,那如果需要在控制器层实现属性注入那怎么办呢?那实际上还有一个接口,用来让我们去创建控制器,那就是IControllerFactory接口,这个接口有两个方法,一个是CreateController方法和ReleaseController方法,顾名思义就是一个是创建控制器,一个是销毁控制器,那我们可以在第一个方法去实现控制器层的属性注入以及一个接口多实现该怎么去获取的思路,如果是属性注入,我们是需要去创建一个特性用来标记这个属性是用来从容器中获取对象的,我们可以在控制器层或者其他类中使用类似的方法去操作属性注入赋值,如果是一个接口多实现呢,也是需要去定义两个特性,一个特性标记在实现类上面,并且构造函数中有一个string类型的参数,用来标记是在容器中 注入的时候使用某个名称用来标识这个类型,其次在我们进行获取这个类型的时候需要在参数或者属性用我们定义的第二个特性标记这个参数或者属性是从容器中获取的是哪一个名称哪一个类型的对象,这样就可以实现一个属性注入和一个接口多实现的一个操作。
总结
以上是我个人实现自定义IOC的一个解决思路,并且在net core5以及net core6中实现,且5到6实现了无缝升级,没有任何错误,希望能够对各位读者有所帮助。还是希望众多道友能够多解读源码,去查看core框架开发者提供给我们暴露给我们的自定义拓展的一些接口和抽象类。后面我依旧会持续更新core自定义相关的东西,会包括配置还有日志等其他方面的东西,多线程方面的代码已经写完,可以在QQ群6406277群文件中进行查找,也可以查看哪个net群有叫四川观察的,那个就是我。IL后面我也写了很多东西,后续也会一一奉上。在此,谢谢各位看官浏览。
Asp.net core自定义依赖注入容器,替换自带容器的更多相关文章
- ASP.NET Core之依赖注入
本文翻译自:http://www.tutorialsteacher.com/core/dependency-injection-in-aspnet-core ASP.NET Core支持依赖注入,依赖 ...
- 几十行代码实现ASP.NET Core自动依赖注入
在开发.NET Core web服务的时候,我们习惯使用自带的依赖注入容器来进行注入. 于是就会经常进行一个很频繁的的重复动作:定义一个接口->写实现类->注入 有时候会忘了写Add这一步 ...
- 【ASP.NET Core】依赖注入高级玩法——如何注入多个服务实现类
依赖注入在 ASP.NET Core 中起中很重要的作用,也是一种高大上的编程思想,它的总体原则就是:俺要啥,你就给俺送啥过来.服务类型的实例转由容器自动管理,无需我们在代码中显式处理. 因此,有了依 ...
- ASP.NET Core:依赖注入
ASP.NET Core的底层设计支持和使用依赖注入.ASP.NET Core应用程序可以利用内置的框架服务将它们注入到启动类的方法中,并且应用程序服务能够配置注入.由ASP.NET Core提供的默 ...
- asp.net core ioc 依赖注入
1.生命周期 内置的IOC有三种生命周期: Transient: Transient服务在每次被请求时都会被创建.这种生命周期比较适用于轻量级的无状态服务. Scoped: Scoped生命周期的服务 ...
- 用工厂模式解决ASP.NET Core中依赖注入的一个烦恼
这是最近在实际开发中遇到的一个问题,用 asp.net core 开发一个后端 web api ,根据指定的 key 清除 2 台 memcached 服务器上的缓存.背景是我们在进行 .net co ...
- ASP.NET Core依赖注入系统学习教程:容器对构造函数选择的策略
.NET Core的依赖注入容器之所以能够为应用程序提供服务实例,这都归功于ServiceDescriptor对象提供的服务注册信息.另外,在ServiceDescriptor对象中,还为容器准备了3 ...
- asp.net core 自定义 Policy 替换 AllowAnonymous 的行为
asp.net core 自定义 Policy 替换 AllowAnonymous 的行为 Intro 最近对我们的服务进行了改造,原本内部服务在内部可以匿名调用,现在增加了限制,通过 identit ...
- 【半小时大话.net依赖注入】(下)详解AutoFac+实战Mvc、Api以及.NET Core的依赖注入
系列目录 上|理论基础+实战控制台程序实现AutoFac注入 下|详解AutoFac+实战Mvc.Api以及.NET Core的依赖注入 前言 本来计划是五篇文章的,每章发个半小时随便翻翻就能懂,但是 ...
随机推荐
- 数据结构与算法——克鲁斯卡尔(Kruskal)算法
目录 应用场景-公交站问题 克鲁斯卡尔算法介绍 克鲁斯卡尔算法图解 克鲁斯卡尔算法分析 如何判断回路? 代码实现 无向图构建 克鲁斯卡尔算法实现 获取一个点的终点解释 应用场景-公交站问题 某城市新增 ...
- 使用node-gyp编写简单的node原生模块
通过样例,让我们了解如何编写一个node的原生模块.当然,这篇文章还有一个目的,是为了方便以后编写关于node-gyp的文章,搭建初始环境. 基于node-addon-api 基于node-addon ...
- 9.亿级流量电商系统JVM模型参数预估方案
1. 需求分析 大促在即,拥有亿级流量的电商平台开发了一个订单系统,我们应该如何来预估其并发量?如何根据并发量来合理配置JVM参数呢? 假设,现在有一个场景,一个电商平台,比如京东,需要承担每天上亿的 ...
- 讲讲java中线程池的实现
今天跟一个同学谈到java中的线程池的实现,才发现有些知识点已经记不清了,所以特意把源码打开,对官方文档做了些说明. 其实这些理解了之后,读懂源码应该是没多大问题了,有感兴趣的小伙伴们可以看完说明后自 ...
- Bug概述、状态、类型、级别、优先级提交和Bug生命周期管理
缺陷概述: 1)缺陷(Defect):是指存在于软件之中偏差,可被激活,以静态形式存在于软件内部,相当于Bug. 2)故障(Fault):当缺陷被激活后,软件运⾏中出现的状态,可引起意外情况,若不加处 ...
- props&attrs provide inject
defineComponent({ props: {// 1 } setup (props, {attrs, emit}) { } }) 一,组件传值: 父传子: 1.如果没有在定义的props中声明 ...
- 更好的 java 重试框架 sisyphus 的 3 种使用方式
回顾 我们前面学习了 更好的 java 重试框架 sisyphus 入门简介 更好的 java 重试框架 sisyphus 配置的 2 种方式介绍 更好的 java 重试框架 sisyphus 背后的 ...
- Beta阶段初始任务分配
项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 团队项目-计划-Beta阶段说明书 一.Beta阶段总体规划 根据用户反馈与测试结果修复alpha版本的bu ...
- UltraSoft - Beta - Scrum Meeting 9
Date: May 25th, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 记录Scrum Meeting Liuzh 前端 用户忘记密码界面初稿完成 Kkk ...
- Python课程笔记(六)
今天上课补上了上次未学完比较重点的鼠标和键盘事件,同时开始学习运用turtle进行绘图. 本次课程的代码: https://gitee.com/wang_ming_er/python_course_l ...