2012-11-03 42 views
7

我正在嘗試使用ninject注入物業。鑑於下面ninject模塊中的兩個綁定,我預計ConcreteDependency將被注入B
但是,WhenInjectedInto似乎並不考慮被注入的類型,只是目標的聲明類型(在這種情況下屬性)。基礎類Ninject物業注入

有沒有辦法達到我預期的行爲?

static void Main(string[] args) 
{ 
    var kernel = new StandardKernel(new TestModule()); 
    var b = kernel.Get<B>(); 
    var c = kernel.Get<C>(); 
} 

class TestModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IDependency>().To<EmptyDependency>(); 
     Bind<IDependency>().To<ConcreteDependency>().WhenInjectedInto<B>(); 
    } 
} 

abstract class A 
{ 
    [Inject] 
    public IDependency Dependency { get; set; } 
} 

class B : A {} 

class C : A {} 

interface IDependency {} 

class EmptyDependency : IDependency { } 

class ConcreteDependency : IDependency { } 
+0

如何在NInject中註冊A,B和C? –

+0

您不必在Ninject中。由於'B'和'C'是具體類,因此不需要明確註冊。 – Gibsnag

回答

4

爲了檢查具體類型,您可以在IRequest界面上使用ParentContext.Plan.Type。這應該會給你從WhenInjectedInto預期的行爲。例如:

When(req => req.ParentContext.Plan.Type == typeof(B)) 
8

如果可能的話,您應該使用構造函數注入來代替屬性注入。這是Mark Seeman推薦的一種更好的技術,因爲通過構造函數使對象構造所需的依賴性和對象簽名更具表現力。代碼應該如下所示:

abstract class A 
    { 
     public IDependency Dependency { get; private set; } 

     public A (IDependency dependency) 
     { 
      Dependency = dependency; 
     } 

    } 

    class B : A 
    { 
     public B (IDependency dependency) 
      : base(dependency) 
     { 

     } 
    } 

    class C : A 
    { 
     public C (IDependency dependency) 
      : base(dependency) 
     { 

     } 
    } 

    interface IDependency { } 

    class EmptyDependency : IDependency { } 

    class ConcreteDependency : IDependency { } 

配置將與您的示例相同。下面的測試通過

[Test] 
    public void TestSpecificBindingToObjectB() 
    { 
     var kernel = new StandardKernel(new TestModule()); 
     var b = kernel.Get<B>(); 
     var c = kernel.Get<C>(); 

     Assert.AreNotEqual(b.Dependency.GetType(), c.Dependency.GetType()); 
     Assert.AreEqual(typeof(ConcreteDependency), b.Dependency.GetType()); 
    } 

如果你有一個默認的實現一個可選的依賴,你都OK與Inject屬性裝飾你的類,可以從請求拉家長信息,像這樣:

class TestModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IDependency>().To<EmptyDependency>(); 
     Bind<IDependency>().To<ConcreteDependency>().When(req =>req.ParentContext.Request.Service == typeof(B)); 
    } 
} 

然後,上面給出的相同測試傳遞給您的類屬性注入等級。

+1

謝謝,但不幸的是我想讓它爲財產注入工作。在這種情況下,依賴項可以具有合理的默認值(Empty Dependency),所以我將它從構造函數注入移動到屬性注入以避免具有太多構造函數參數。 – Gibsnag

+1

我試圖使用'when'擴展方法來使用一個謂詞,它將使用被注入的類型,而不是屬性的聲明類型,但不能解決如何從'IRequest'獲得必要的信息。 – Gibsnag

+0

我已經更新了我的答案,關於您的可選依賴項的情況與默認實現 –