依赖注入 DI
控制反转 IOC
A 依赖B,就A只用B,但对B怎么产生与销毁不管
讨论下:A如何可以用到B?
1)当作参数传给A,可以利用构造函数传,当然也可以当作方法参数传
2)B是A的属性,赋值传入即可
不用每次在用的时候传进去,A想用B的时候 直接用就行
IOC Container出来了
OK,既然A不用管B的生成与销毁,那么IoC 容器 怎么实现 B的生成与销毁,还有如何将B传给A了?
IOC容器流程如下:
注册服务:告诉容器规则,这个接口最终用哪个实现体,就是服务与实现的映射表,
AddScoped<IServiceB, ServiceB>()时,容器就记录下了一条规则:“有人要 IServiceB?好的,那我就创建一个 ServiceB的实例给他解析与注入:当你的应用程序运行时,框架(如 ASP.NET Core)需要创建某个对象(例如一个控制器
MyController,也就是对象 A)时,会发生以下自动化的神奇步骤:- 发现依赖:框架发现
MyController的构造函数需要一个IServiceB类型的参数 - 递归解析:容器(
IServiceProvider)接到指令后,会查看自己内部的注册表。它发现IServiceB对应ServiceB。于是,它开始动手创建ServiceB的实例。关键点:如果ServiceB本身也有依赖(比如它需要IServiceC),那么容器会递归地重复这个过程:先解析IServiceC的实例,然后将其注入到ServiceB中,最后完成ServiceB的创建。这个过程会构建出一完整的“对象依赖树” 。 - 完成注入:容器将创建好的
ServiceB实例(也就是对象 B)传递给MyController的构造函数。至此,依赖注入完成
生命周期管理:容器如何“销毁”对象
对象的销毁方式完全取决于其注册时指定的生命周期。.NET Core 内置了三种主要生命周期 :
| 生命周期 | 注册方法 | 对象创建与销毁时机 |
|---|---|---|
| 瞬时 | AddTransient |
每次请求都会得到一个新实例。容器不负责销毁,由 .NET 的垃圾回收器在对象不再被使用时自动回收。 |
| 作用域 | AddScoped |
每次网络请求(或一个自定义的作用域内)共享同一个实例。当请求结束时,容器会释放(Dispose)那些实现了 IDisposable接口的实例。这是管理数据库连接等资源的关键机制。 |
| 单例 | AddSingleton |
整个应用程序生命周期内只有一个实例。容器会一直持有该实例,直到应用程序关闭时才会将其释放。 |
所以,对于 B 的销毁:
- 你不需要也不能手动
new和delete(销毁)。 - 容器的责任就是根据上述规则,在正确的时机(特别是对于
Scoped和Singleton服务)调用它们的Dispose()方法以释放资源(如数据库连接、文件句柄)。
💡 核心价值总结
通过这套机制,.NET Core 的 IoC 容器实现了:
- 控制反转:将对象的创建权从业务代码反转到容器。
- 依赖注入:由容器负责将依赖项注入到需要它的对象中。
- 解耦:
MyController只依赖于抽象IServiceB,而不关心具体的实现是谁,更不关心它如何创建和销毁。这使得代码更容易测试(测试时可以注入一个模拟实现)和维护 。
转载请注明:深圳彦祖 » 依赖注入DI与控制反转IOC核心解析
