我需要更多帮助来“了解”像 Ninject 这样的 DI 框架如何超越基础。
取 Ninject 样本:
class Samurai {
private IWeapon _weapon;
[Inject]
public Samurai(IWeapon weapon) {
_weapon = weapon;
}
public void Attack(string target) {
_weapon.Hit(target);
}
}
如果没有 DI 框架(即上面的 [Inject] 引用),引用类将类似于:
class Program {
public static void Main() {
Samurai warrior1 = new Samurai(new Shuriken());
Samurai warrior2 = new Samurai(new Sword());
warrior1.Attack("the evildoers");
warrior2.Attack("the evildoers");
}
}
...您正在更新所有内容。是的,您已经删除了 Samurai 中的依赖项,但现在您在链上又多了一个依赖项。简单的。
使用 Ninject,您可以通过以下方式摆脱更新:
class Program {
public static void Main() {
IKernel kernel = new StandardKernel(new WarriorModule());
Samurai warrior = kernel.Get<Samurai>();
warrior.Attack("the evildoers");
}
}
但是,这是我困惑的领域:如果没有制作某种服务定位器来有效地更新适用的内核和模块(即 .IoC.TypeResolver.Get<>()),那么 a) 最好的方法是什么?不必到处都更新内核(到处都有服务定位器引用?),并且b)更重要的是,当你有一个很大的长链时,你的依赖关系和它们自己的依赖关系,你把它带到了一路传递注入的极端我确信这是一个严重的反模式(一个朋友称之为“热土豆依赖注入”反模式)。
换句话说,我认为 DI 框架的魔力的一部分是您不必一直插入依赖关系(即您的第一个引用在其构造函数中包含 10 个参数,这些参数都与任何事情,直到沿着链走得更远) - 我的困惑的魔法或解决方案在哪里,这样依赖关系就不会不断地被向上和向上引用,或者服务定位器引用无处不在。
对我来说,进一步混淆水域是如果使用 DI 框架,那么处理引用类需要 IList 的场景的最佳方法是什么,该 IList 通常会放在构造函数中(即 new ReferencedClass(myList)),除了在像字符串数据库连接字符串这样的简单情况下,不会飞。只需创建一个属性并在更新它/DI 框架服务定位后设置它?IE
var referencedClass = IoC.Get<IReferencedClass>();
referencedClass.MyList = myList;
总而言之,我认为这是一个我收到后可能会感到尴尬的帖子,但现在,我已经多次撞墙试图确定最佳方法。