控制反转(IoC) 和 依赖注入 (DI)
目录
控制反转是思想,依赖注入是实现手法
一、什么是“控制反转”(IoC)
简单解释
控制反转就是:把“创建对象”和“管理对象生命周期”的权力,从你自己(开发者)手里,交给框架或容器来做。
武侠比喻:
以往你学武必须自己去找师傅、拜师、求秘籍;
现在换成武林总盟替你安排师傅、安排课程、分配秘籍。
你只管用,
不管选人、不管安排、不管管理。
这就是“控制反转”。
二、依赖注入(DI)是什么?
简单解释
依赖注入就是实现控制反转的具体技术手段之一。
控制反转是思想,
依赖注入是实现手法。
依赖注入本质就是:
“别人把你需要的东西主动给你,而不是你自己 new 它。”
举例演示(没有 DI 时的写法)
public class UserService
{
private readonly UserRepository _repo;
public UserService()
{
_repo = new UserRepository(); // 自己 new
}
}问题:
- UserService 依赖 UserRepository
- 但它自己 new,自我绑定
- 想换 Repository? 很难
就像:
“洪七公就教你降龙十八掌了,你不能换师傅,也不能换掌法。”
使用 DI 之后的写法(推荐)
public class UserService
{
private readonly IUserRepository _repo;
public UserService(IUserRepository repo)
{
_repo = repo;
}
}不再自己 new,而是 别人(DI 容器)传进来。
武侠比喻
“你只是说你想学掌法,但不指定是哪门派的。”
武林总盟会根据注册信息(Register)给你安排:
- 注册为 Register<IUserRepository, SqlUserRepository>() —— 给你 SQL 门派师傅
- 注册为 Register<IUserRepository, MemoryRepository>() —— 给你快速入门师傅
你不需要任何修改,只是换了注册方式。
三、IoC 和 DI 的关系
你可以这样记:
名称定义关系**IoC(控制反转)**一种思想“你不 new,我来帮你 new”**DI(依赖注入)**实现 IoC 的最常用方式IoC 的主要手段
武侠比喻:
- IoC 是“武林总盟替你安排师傅”的思想
- DI 是“安排师傅时实际派遣人类、送秘籍、指派教学”的手段
四、DI 的三种注入方式
1.构造函数注入(最常用)
public MyService(IOtherService service)
{
_service = service;
}优点:
- 最稳定、强制依赖
- 适用于大部分情况
2.属性注入
public IOtherService Service { get; set; }用于:
- 有些依赖是可选的
3. 方法注入
public void Init(IOtherService service)
{
_service = service;
}用于:
- 仅某个方法需要依赖时
五、为什么需要 IoC 和 DI?
1. 解耦
不用写:
var repo = new UserRepository();改为:
IUserRepository repo更容易替换实现类。
2. 更容易测试(Mock)
new UserService(new FakeRepository());可以替换为假数据仓库做单元测试。
3. 更方便扩展
想换:
- 数据库驱动
- 业务逻辑实现
- 缓存方式
- 日志框架
只需修改注册,不改核心代码。
4. 管理生命周期
IoC 容器可以帮你决定对象如何存在:
- Transient(每次 new)
- Scoped(每次请求)
- Singleton(全局唯一)
你不用操心对象什么时候销毁。
六、实际 WPF / Prism 示例
你之前看到的:
containerRegistry.Register<IUserService, UserService>();
containerRegistry.RegisterSingleton<ICurrentUserService, CurrentUserService>();解释:
注册含义Register每次 Resolve 时 new 一个RegisterSingleton整个程序使用同一个实例
XAML 中的 View-ViewModel 注入也是 DI 的应用。
总结
- IoC 是思想:让别人控制对象创建,而不是你自己控制。
- DI 是技术:别人把你需要的东西“注入”给你。
- DI 让程序解耦、可测试、可扩展、可维护。
- 容器(Autofac、Unity、Prism、ASP.NET Core 内置 DI)负责注入。