使用Ninject,我可以从接口创建一个实例而不暴露我的具体类吗?

时间:2011-03-15 16:36:28

标签: c# dependency-injection inversion-of-control ninject

到目前为止我见过的样本看起来像这样:

像这样编写你的代码......

public class Samurai {
  public IWeapon Weapon { get; private set; }
  public Samurai(IWeapon weapon) {
    Weapon = weapon;
  }
}

Ninject可以将界面映射到具体的类型......

public class WarriorModule : NinjectModule {
  public override void Load() {
    Bind<IWeapon>().To<Sword>();
  }
}

所以当我在武士对象中说var samurai = kernel.Get<Samurai>();时,我的IWeapon自动成为剑。

这很酷,但如果我只想要没有武士的ISword并且混凝土剑被标记为内部呢?

目前,我使用自制的依赖解析器,我可以说var sword = DependencyResolver.Current.Resolve<ISword>();并且它给了我一个Sword演员作为ISword。我的具体类被标记为内部,因此开发人员必须通过我的依赖项解析器来创建实例。 Ninject有类似的东西吗?

还有一个额外的问题,我用自定义的“DefaultConcreteType”属性修饰我的接口,如果不存在映射,我的依赖解析器可以使用该属性。 Ninject有这样的东西吗?

由于

3 个答案:

答案 0 :(得分:15)

将接口绑定到具体类型时,可以请求该接口的实例并获取具体类型。在您的示例中,您可以执行此操作:

var sword = kernel.Get<ISword>();

这会给你一个具体的Sword对象。您也可以使用绑定系统做更多事情。您甚至可以Bind<ISword>().ToMethod(MySwordFactory);并根据请求上下文编写一个方法来获取Swords。

您可以做的另一件事是根据注入的类型更改绑定工作的方式。例如,您可以在自定义类上公开属性,如下所示:

public class MyClass {
    [Inject]
    public ISword Sword { get; set; }
}

然后你可以绑定到基于MyClass的特定ISword实现:

Bind<ISword>().To<Sword>().WhenInjectedInto<MyClass>();

还有很多选择,但这应该给你一个粗略的概述。

答案 1 :(得分:0)

我建议使用可以创建ISword的抽象工厂。这比DependencyResolver有一个优势,因为它可以创建的类型是有界的(到ISword)。

您的抽象工厂需要公开,就像您的DependencyResolver一样。

答案 2 :(得分:0)

这并没有直接回答你的问题,但我知道在Unity中,你可以通过使用Config文件而不是在代码中连接依赖项来实现。不幸的是,Ninject不支持配置文件。

您的替代方法是使用非泛型重载:

Bind(typeof(IWeapon)).To(typeof(Sword));

然后你应该可以做类似的事情:

Bind(typeof(IWeapon)).To(Type.GetType("MyNamespace.MyInternalSword"))

但如果你问我,那就太大了......