目录
ServiceCollection/ServiceProvider
为什么要用IOC
- 为什么要用IOC呢?
- Controller调用BLL,BLL调用DAL,再写个DBHelper的类,DAL在调用DBHelper里面的方法,项目不 也照样做的飞起吗?
- 这种做法其实最核心的思想就是职责分离,一个DAL对象可以被多个BLL对象使用,一个BLL对象也 可以被多个Controller对象使用。
- 这种做法有一个比较大的问题,那就是目前只做到了逻辑的复用,但是并没有做到资源的复用。
- 本来应该多个Controller对象共用一个BLL对象,多个BLL对象又共用一个DAL对象。
- 现在变成了一个Controller对象创建了多个重复的BLL对象,然后多个BLL对象又创建了多个重复的 DAL对象。
- 问题就是很多对象其实只需要创建一次就够了,创建那么多也没有什么意义。
- 所以针对对象重复创建的问题,可以用单例模式来解决。
- 单例模式要确保整个应用程序中有且仅有一个实例,对象只能被创建一次。
- 所以用单例模式创建的对象必须是该单例类私有的静态对象。
- 问题就是它是静态对象,静态对象会被存储在”静态存储区”里面,一直到程序退出,才会被回收。
- 那也就意味着通过单例模式创建的对象越多,内存占用的也就越多。
- 那有些小公司也不在乎这点内存,项目就这么大,占不了多少内存,占这点内存无所谓,不够了再加。
- 那还有一个问题,就是后面我觉得这个BLL对象起的名字不妥,想改一下,那所有用到这个BLL对象 的Contoller对象都得改。
- 那有些人说了,那我不改不就行了,项目能跑能用就行,命名没有那么严格。
- 那还有一个问题,如果说现在new一个简单的对象,那没啥问题。如果现在new的这个对象比较复杂, 在创建的时候还需要先new其它对象。其它对象在new的时候也比较复杂,比如构造函数里面需要传 入很多参数,new完还要给很多的属性赋值。刚好需要传入的参数还有需要进行赋值的属性都是一些 配置性的东西,会随着业务的需求不断的在变。那这个时候,你就得需要修改每一个用到了该对象的 地方,项目越大,业务越复杂,改的就越多。
- 所以就需要IOC容器来创建对象,进行解耦,把对象之间的这种依赖关系交给IOC容器来处理,就完 事了。
- 但是一些小公司,做的一些小项目,需求也没那么复杂,也就没有必要用IOC。
IOC的实现原理
- 根据传入的泛型类型,获取它的Type类型对象。
- 根据Type类型的对象,调用GetConstructors方法获取它的构造函数,是一个ConstructorInfo数组。
- 然后进行构造函数的筛选,找出有构造函数参数的ConstructorInfo对象。
- 然后调用ConstructorInfo对象的GetParameters方法,获取全部的构造函数参数,是一个ParameterInfo 类型的数组。
- 然后对这个ParameterInfo类型的数组进行遍历,调用每个ParameterInfo对象的ParameterType属性来 获取ParameterInfo对象的Type类型对象,把它放到一个List集合里面保存起来。
- 最后调用Activator对象的CreateInstance方法创建对象,CreateInsatance方法的第一个参数就是传入 的泛型类型的Type类型对象,第二个参数就是存放ParameterInfo对象的Type类型对象的集合,但是 得调用ToArray方法把它转成数组。
- 大概就是这么一个思路,更具体的细节现在也记不住了。
IOC(控制反转)
- IOC的思想就是把对象之间的依赖关系交给容器来处理,上层不再依赖于下层,而是依赖于抽象,IOC 容器来实例化下层。
- 所以IOC它就是一种目标,让程序解耦,让第三方的IOC容器来创建对象,DI是实现IOC的手段。
- IOC也可以理解为一个实例化对象的工厂,它的这种思想也符合设计模式中的依赖倒置原则。
DI(依赖注入)
- DI就是依赖注入。
- 依赖注入就是构造A对象的时候发现先需要构造B对象,那么先构造B对象然后再构造A对象。
- 就是让对象能够自动的进行注入。
IOC生命周期
- IOC的生命周期主要有三种。
- 第一种是瞬时,AddTransient,服务随时创建随时销毁。
- 第二种是单例,AddSingleton,从程序启动开始到程序被终止为止,服务永远只构造一次。
- 第三种是作用域单例,AddScoped,服务在这一次请求中,只构造一次。
ServiceCollection/ServiceProvider
- 在.NetCore中关于IOC有两个重要的对象。
- 第一个是ServiceCollection对象,它只支持构造函数的注入,用来添加服务,是一个用来存放服务注册 信息的集合。
- 第二个是ServiceProvider对象,它是用来获取IOC容器的实例,可以调用ServiceCollection对象的 BuildServiceProvider方法创建ServiceProvider对象。
Scrutor
- 在.NetCore中可以通过Scrutor来简化DI服务的注入方式,因为如果服务太多的话,去Add添加服务 很容易出错。
- Scrutor它不是依赖注入框架,而是.NetCore内置的DI扩展包。
- 可以根据一些约定来进行DI服务的自动注册,比如以Service结尾的服务,就可以进行自动注入,不 需要每个手动都去Add添加。
IOC单接口多实例
定义集合类型获取所有实例。
构造函数注入优势
- 通过构造函数的方式注入对象,可以声明为readonly,动态常量,保证对象的不可变性。
- 可以保证依赖不为空,因为readonly声明的对象必须在声明时初始化或者在构造函数执行时初始化。