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的依赖注入 前言 本来计划是五篇文章的,每章发个半小时随便翻翻就能懂,但是 ...
随机推荐
- 深度学习——手动实现残差网络ResNet 辛普森一家人物识别
深度学习--手动实现残差网络 辛普森一家人物识别 目标 通过深度学习,训练模型识别辛普森一家人动画中的14个角色 最终实现92%-94%的识别准确率. 数据 ResNet介绍 论文地址 https:/ ...
- 【Java虚拟机2】Java类加载机制
前言 JAVA代码经过编译从源码变为字节码,字节码可以被JVM解读,使得JVM屏蔽了语言级别的限制.才有了现在的kotlin.Scala.Clojure.Groovy等语言. 字节码文件中描述了类的各 ...
- python png图片生成gif
有时候写代码就是这样别人把代码写好你在后面加一个句号就行了 我很懒不想写成函数,你自己来吧.有注释就不错了 这个依赖一个图像处理库pillow,轮子就是轮他不是车 import imageio imp ...
- MySQL:怒刷牛客网“sql实战”
MySQL:怒刷牛客网"sql实战" 在对MySQL有一定了解后,抽空刷了一下 牛客网上的 数据库SQL 实战,在此做一点小小的记录 SQL1 查找最晚入职员工的所有信息 sele ...
- BUAA_2020_软件工程_结对项目作业
项目 内容 这个作业属于哪个课程 班级博客 这个作业的要求在哪里 作业要求 我在这个课程的目标是 掌握软件工程的思路方法 这个作业在哪个具体方面帮助我实现目标 学习结对编程 教学班级 006 项目地址 ...
- [火星补锅] 水题大战Vol.2 T2 && luogu P3623 [APIO2008]免费道路 题解
前言: 如果我自己写的话,或许能想出来正解,但是多半会因为整不出正确性而弃掉. 解析: 这题算是对Kruskal的熟练运用吧. 要求一颗生成树.也就是说,最后的边数是确定的. 首先我们容易想到一个策略 ...
- 零基础入门必备的Linux命令和C语言基础
文件和目录(底部有视频资料) cd /home 进入 '/ home' 目录' cd - 返回上一级目录 cd -/- 返回上两级目录 cd 进入个人的主目录 cd ~user1 进入个人的主目录 c ...
- Shell脚本学习笔记之(自动填充函数模板)
其实,vii 就是写的一个脚本,跟 vi 没半毛钱关系,只不过借用一下这个名字而已.那这个脚本长什么样呢?look: 下面来详细的解析上面的代码,来看第1行: #!/bin/bash 这是Shell脚 ...
- CF #749
A 题意 有个长度为n的序列, 每个数互不相同, 求总和最大的最长子序列, 并输出每个i: 题解 emmmmmm, 刚开始看到这个数据和题解被迷惑了, 以为有什么顺序, 并且一直在想一些复杂度较高的算 ...
- linux 内核源代码情景分析——linux 内核源代码中的C语言代码
linux 内核的主体是以GNU的C语言编写的,GNU为此提供了编译工具gcc.GNU对C语言本身作了不少扩充. 1) gcc 从 C++ 语言中吸收了"inline"和" ...