14

我需要更多帮助来“了解”像 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;

总而言之,我认为这是一个我收到后可能会感到尴尬的帖子,但现在,我已经多次撞墙试图确定最佳方法。

4

1 回答 1

3

至于“烫手山芋”依赖性问题,这不必发生。依赖注入框架会为您处理这个问题。

例如,如果 Class1 依赖于 Class2,而 Class2 依赖于 Class3,则无需将 Class3 注入 Class1 以适应 Class2 依赖关系。当您请求 Class1 时,内核将为您遍历依赖链并自动解析下游依赖(只要所有正在运行的类都已在内核中注册)。

Class1 依赖 Class2 依赖 Class3

Class1 构造函数根本不需要提及 Class3。

至于第二个问题,如何或是否适应这取决于框架。使用 Ninject,我认为您可以使用Bind().To().WithConstructorArgument()语法将新的 List 项提供给构造函数。

于 2010-01-03T00:00:41.017 回答