2010-06-23 79 views
14

請考慮以下代碼。在Ninject中注入接口陣列

public interface IFoo { } 


public class Bar 
{ 
    public Bar(IFoo[] foos) { } 
} 


public class MyModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IFoo[]>().ToConstant(new IFoo[0]); 
     // ToConstant() is just an example 
    } 
} 


public class Program 
{ 
    private static void Main(string[] args) 
    { 
     var kernel = new StandardKernel(new MyModule()); 
     var bar = kernel.Get<Bar>(); 
    } 
} 

當我嘗試運行該程序時,出現以下異常。

錯誤激活的IFoo
沒有匹配的綁定是可用的,並且類型不是自可綁定。
激活路徑:
2)依賴的IFoo注射到型酒吧
1)請求酒吧

的構造的參數FOOS

如何可以注入/結合在Ninject數組?

謝謝你的時間。

編輯:
我的應用程序導入由第三方組件創建的數據。 導入過程應用不同類型的過濾器(例如,不同過濾器接口的實現)。過濾規則經常變化,但過於複雜,無法用純配置(和主過濾器)完成。

我想使添加/編輯過濾器儘可能簡單。我所擁有的是所有過濾器實現所在的程序集。我試圖將每個過濾器接口綁定到以下方法(它提供了該過濾器類型的每個實現的實例)。基本上我想避免在添加/刪除過濾器類時需要更改我的Ninject模塊。

private IEnumerable<TInterface> GetInterfaceImplementations<TInterface>(IContext context) 
    { 
     return GetType().Assembly.GetTypes() 
      .Where(t => typeof (TInterface).IsAssignableFrom(t) && IsConcreteClass(t)) 
      .Select(t => Kernel.Get(t)).Cast<TInterface>(); 
    } 

我在繞過容器DI機制方面感覺有點內疚。這是一種不好的做法嗎?有做這種事情的普遍做法嗎?

決議:
我使用包裝類作爲bsnote建議。

回答

7

這在很大程度上是對@ bsnote的答案(我已經+ 1d)的重述,這可能有助於理解爲什麼它以這種方式工作。

Ninject(和其他DI /插件框架)有兩個獨特的設施:

  1. 或者綁定到一個明確的實施服務(Get
  2. 設施的概念,使人們得以獲得一組服務[即一個然後以編程拾取的一個或以某種方式跨越聚合](在Ninject GetAll/ResolveAll

你的示例代碼恰巧使用SY的與上述2.相關的ntax。 (例如。在MEF,一個通常使用[ImportMany]註釋來說明這一點)

我需要的樣本看(看源 - 它真的很短,乾淨,易於遵循)找到一種解決方法。然而,正如@bsnote所說,重構你的需求的一種方法是將數組包裝在一個容器中,或者讓一個你要求的對象(即工廠方法或存儲庫類型構造)

它可能也是有用的你解釋你的真實情況是什麼 - 爲什麼有一個裸體陣列?當然有一些項目構建乞求封裝在這一切的基礎 - 這個問題肯定不會出現太多?

編輯:在擴展中有一組掃描例子,我想會攻擊很多你想要做的事情(在像StructureMap這樣的東西更集成,這顯然有利益和缺點)。

根據您是否嘗試實現約定而不是配置,您可能需要考慮在每種類型的插件上粘貼標記接口。那麼你可以明確地Bind每一個。或者,對於CoC,您可以在編輯過程中使ModuleLoad()例程循環遍及您生成的一組實現(即,大量單個的Get)。

無論哪種方式,當您有多個註冊時,您可以愉快地'請求'T[]IEnumerable<T>並獲得全套。如果你想明確地實現這一點(即服務定位器及其所暗示的一切 - 就像你正在做的那樣,你可以使用GetAll對它們進行批處理,所以你沒有按照你所做的那樣進行循環。

不知道,如果你做了這個連接,或者如果我失去了一些東西無論哪種方式,我希望這是教你堅持一些代碼到的問題,因爲它講> 1000個字:P。

+0

我選擇這個答案,因爲它更詳細。謝謝(+1)給bsno也是! – 2010-06-24 14:12:18

4

這對我來說也是個問題。 Ninject將注入數組中的每個項目而不是數組本身,因此您應該爲數組項目的類型定義映射。實際上,不可能將數組映射爲當前版本的Ninject類型。解決方案是在數組周圍創建一個包裝。例如,如果它適合你,則可以使用懶惰類。或者你可以創建自己的包裝。

9

Ninject支持多注射,這將解決您的問題https://github.com/ninject/ninject/wiki/Multi-injection

public interface IFoo { } 
public class FooA : IFoo {} 
public class FooB : IFoo {} 

public class Bar 
{ 
    //array injected will contain [ FooA, FooB ] 
    public Bar(IFoo[] foos) { } 
} 

public class MyModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IFoo>().To<FooA>(); 
     Bind<IFoo>().To<FooB>(); 
     //etc.. 
    } 
}