如何在控制台应用中通过Pure DI实现控制反转(不使用IoC容器)
完全可以通过Pure DI的方式实现解耦,无需引入任何第三方IoC容器。核心思路是将「实例创建的能力」作为依赖注入到工厂中,而非让工厂直接依赖具体实现,所有实现的绑定逻辑统一上移到程序的组合根(也就是入口Main方法所在的最高层级)。
改造步骤
1. 重构GummyFactory
将创建IGummyPackage、IGummyBag、IGummyBear实例的逻辑通过构造函数委托的形式注入,让工厂只依赖接口,完全和具体实现解耦:
public class GummyFactory : Factory<IGummyPackage> { private readonly Func<IGummyPackage> _packageFactory; private readonly Func<IGummyBag> _bagFactory; private readonly Func<IGummyBear> _bearFactory; // 构造函数注入三个创建实例的工厂委托 public GummyFactory(Func<IGummyPackage> packageFactory, Func<IGummyBag> bagFactory, Func<IGummyBear> bearFactory) { _packageFactory = packageFactory; _bagFactory = bagFactory; _bearFactory = bearFactory; } public override IGummyPackage AssembleProducts() { IGummyPackage gummyPackage = _packageFactory(); Random rnd = new Random(); for (int i=1;i<=GummyBearPackageConfiguration.NumberOfGummieBagsPerPackage;i++) { IGummyBag gummyBag = _bagFactory(); gummyBag.BagNumber = i; for (int b =1; b <= GummyBearPackageConfiguration.NumberOfGummiesPerBags;b++) { IGummyBear gummyBear = _bearFactory(); gummyBear.GummyID = b; int flvr = rnd.Next(0, 5); gummyBear.flavor = (GummyFlavor)flvr; gummyBag.GummyBears.Add(gummyBear); } gummyPackage.GummyBags.Add(gummyBag); } return gummyPackage; } }
2. 在组合根绑定实现
所有具体实现的绑定逻辑都放在入口Main方法中,后续替换实现只需要修改这一处即可,无需调整工厂内部逻辑:
class Program { static void Main(string[] args) { // 加载配置 GummyBearPackageConfiguration.NumberOfGummieBagsPerPackage = 24; GummyBearPackageConfiguration.NumberOfGummiesPerBags = 7; // 这里统一绑定具体实现,后续换环保纸盒仅需修改bagFactory对应的逻辑 var gummyFactory = new GummyFactory( packageFactory: () => new GummyPackage(), bagFactory: () => new GummyBag(), bearFactory: () => new GummyBear() ); IGummyPackage gummyPackage = gummyFactory.AssembleProducts(); OpenPackage(gummyPackage); Console.ReadLine(); } // 注意这里要把遍历的类型改为接口,避免和具体实现耦合 public static void OpenPackage(IGummyPackage package) { Console.WriteLine($"Opening Gummy Package: \n"); foreach (IGummyBag bag in package.GummyBags) { Console.WriteLine($"Opening Gummy Bag #{bag.BagNumber}"); foreach (IGummyBear bear in bag.GummyBears) { Console.WriteLine( $"Gummy Number {bear.GummyID} is {bear.flavor.ToString()} flavor"); } } } }
改造收益
- 完全基于原生C#语法实现,无任何第三方依赖,符合你的项目限制
- 动态创建实例的需求完美适配:注入的是创建实例的委托,运行时需要多少个实例就调用多少次委托,不受构造注入只能注入固定实例的限制
- 符合开闭原则:后续更换任意组件实现(比如把GummyBag换成环保硬纸盒),仅需修改组合根的绑定逻辑,无需调整工厂核心的装配代码
内容的提问来源于stack exchange,提问作者Hooplator15
相关产品推荐
相关产品推荐

