依赖注入是控制反转的具体实现形式,控制反转是更高层级的设计思想:前者通过构造函数、属性或方法注入依赖,后者将对象生命周期与依赖关系的控制权移交外部容器统一管理。

控制反转和依赖注入的关系常被误解为并列概念,实则二者并非对等关系,而是明确的包含与被包含结构:依赖注入是控制反转的具体实现形式,控制反转是更高层级的设计思想。以下是厘清该从属关系的步骤:
一、控制反转是顶层设计原则
控制反转定义了“谁来掌控对象生命周期与依赖关系”的根本立场:它要求将原本由类自身承担的对象创建、依赖获取、实例销毁等控制权,移交至外部容器统一管理。这种权责转移本身不规定技术细节,仅确立解耦目标与责任边界。
1、在传统编码中,类A通过new B()主动创建其依赖B,控制流完全由A主导;
2、引入IoC后,A不再持有B的构造逻辑,仅声明所需依赖类型(如接口IB);
3、容器依据注册配置,在运行时决定B的具体实现,并完成整个对象图的组装与生命周期托管。
二、依赖注入是IoC的落地技术手段
依赖注入并非独立于IoC之外的另一套机制,而是IoC原则在代码层面的唯一主流实现路径。它聚焦于“如何把依赖送进去”这一操作问题,提供可执行的注入方式,使IoC思想具备工程可行性。
1、构造函数注入:容器在实例化A时,将已解析的B作为参数传入A的构造方法;
2、属性注入:容器在A实例化后,通过反射设置其公开属性(如public IB Dependency { get; set; });
3、方法注入:容器调用A上标记为注入点的方法(如public void SetDependency(IB b)),传入B的实例。
三、二者不可互换使用
存在控制反转但未使用依赖注入的情况极为罕见且非主流——例如服务定位器模式虽也转移控制权,但需A主动向容器索取依赖,仍保留部分耦合,违背IoC“被动接收”的本质要求。现代框架(如.NET Core DI Container、Spring)均以依赖注入为IoC的默认且标准实现。
1、若仅声明接口依赖却不注入具体实例,则IoC容器无法完成对象解析,将抛出InvalidOperationException: No service for type 'X' has been registered;
2、若手动在类中new依赖对象,即使使用了容器托管其他组件,该类仍处于IoC体系之外,形成IoC孤岛;
3、容器注册语句container.Register










