3

我正在使用Autofac來處理我的應用程序中的依賴注入。爲了不需要明確地進行每一次註冊,我首先使用RegisterAssemblyTypes().AsImplementedInterfaces(),然後只處理那些需要特別配置的註冊。Autofac:解析IEnumerable註冊的同名

我有一個名爲IToolStripPopulator的接口,它有幾個不同的實現,其中有幾個正在使用,但有些不再是(因爲我試圖固體工作並堅持OCP,我通常不會改變它們如果我需要不同的功能,而是讓他們獨立,並創建新的功能,現在就做我需要的功能)。出於這個原因,我需要用兩種方法覆蓋接口的自動註冊:

  • 一個實現是注入到我的主邏輯中,並作爲其他幾個的一個裝飾器。我自然希望通過As<IToolStripPopulator>()來註冊,並完成它,因爲這是我的應用程序的功能目前依賴的實現。
  • 那些其他的實現是隻在該裝飾器類中使用的「內部」填充器。要注入它們,有兩種方法:
    • 將外部實現的構造函數用特定類型顯式連接;這不是很好,也因爲該構造函數將不得不採用我正在使用的內部填充函數的確切數量現在,它不符合OCP。
    • 有外部執行需要IEnumerable<IToolStripPopulator>;這是我想要做的,但這也是我卡住的地方。

我不能讓Autofac解決IEnumerable它自己,因爲它只是解決了接口的所有實現,甚至包括那些我不再使用的還有「外」即我不想在那裏(這可能會導致分辨率無限循環)。

所以我想要做的是這樣的:

// the inner populators 
builder.RegisterType<BrowsersMenuPopulator>().Named<IToolStripPopulator>("inner"); 
builder.RegisterType<ThreadsafeConnectionMenuPopulator>().Named<IToolStripPopulator>("inner"); 

// the decorator implementation 
builder.RegisterType<BrowserAndConnectionMenuPopulator>().As<IToolStripPopulator>().WithParameter(?); 

但是沒有辦法在這一點上,以實際訪問現有註冊。

回答

7

....在這裏,我嘗試了一件事,但我沒有真正期望工作,但它確實如此。

builder.Register(c => c.ResolveNamed<IEnumerable<IToolStripPopulator>>("inner")).As<IEnumerable<IToolStripPopulator>>(); 

沒有,因爲我本來期望,試圖解析名爲「內部」的IEnumerable<IToolStripPopulator>註冊,但IToolStripPopulatorIEnumerable一個註冊名爲「內部」 - 正是因爲我需要它。

然後,這將正確解析並注入裝飾器實現,只需註冊As<IToolStripPopulator>()即可,無需進一步配置。

從形式方面來說,我實際上更希望能夠聲明直接用裝飾器註冊來解決的名稱,因爲那樣會更直觀和靈活(如果我需要解析幾個IEnumerable<IToolStripPopulator>?),但是在很多情況下這應該就夠了。

@ codinghorror的「橡皮鴨問題解決」的概念規則我的每一個工作日....

+4

嘿,我只是需要。謝謝我! – TeaDrivenDev

0

直接指定,我知道的唯一途徑是「新達」直接在您的註冊代碼:

//decorator impl 
builder.Register(c => new BrowserAndConnectionMenuPopulator(c.ResolveNamed<IEnumerable<IToolStripPopulator>>("inner"),...)).As<IToolStripPopulator>(); 

這直接在註冊指定的確切需要的依賴的優勢,但在重新配置BrowserAndConnectionMenuPopulator的依賴關係時失去靈活性的缺點。我包括這個完整性,但老實說,我更喜歡你發現的解決方案。