2009-11-19 72 views
0

我有興趣在我的項目中實現一個IoC容器,但我還沒有看到一個能夠滿足我需要的示例。IoC容器對象範圍

下面是情況,我的應用程序是在WPF中構建的,並使用MVVM模式爲紅外視頻格式創建播放器。在這種格式下,每個視頻實際上由多個「子幀」組成(將其視爲以多個快門速度同時捕捉,以增加數據的動態範圍),每個視頻都顯示在TabControl中。我想使用IoC容器來幫助我爲每個選項卡創建ViewModels,但我有兩個問題。

  1. 我需要一種方法在表示子我創建一個視圖模型爲不能由IoC容器創建,因爲它已經存在的視圖模型的依賴,這樣至少一個對象來傳遞。

  2. 我有視圖內的用戶控件有自己的ViewModels子視圖,所以這些ViewModels也需要由IoC容器創建。這個問題是,儘管控件(和它們的ViewModel)具有不同的關注點,但它們並不完全獨立,因此它們使用了一些協調對象。不幸的是,在我見過的所有示例中,您可以讓IoC容器創建一個新的依賴項實例或具有一個單例,但我需要的是在創建子視圖模型期間受控範圍內的單個實例ViewModel 。

這是很多文字,所以這裏是一些代碼,顯示我在做什麼,我想做什麼。

我現在

有什麼在打開電影代碼:

foreach (var subframe in movieFile) 
{ 
    // Subframes is the ObservableCollection that the TabControl is bound to 
    Subframes.Add(new SubframeViewModel(subframe)); 
} 

在SubframeViewModel:

我想有在不改變現有sematics

在打開電影代碼:

foreach (var subframe in movieFile) 
{ 
    Subframes.Add(container.Resolve<SubframeViewModel>()); 
} 

在SubframeViewModel:

public SubframeViewModel(ISubframe subframe, ImageViewModel imageModel, 
          FrameControlViewModel frameModel) 
{ 
    _subframe = subframe; 

    ImageViewModel = imageModel; 

    FrameControlViewModel = frameModel; 
} 

在現實中,也有更多的協調和視圖模型對象參與,但圖案是相同的。這就是說,我認爲你可以看到爲什麼我對這裏的IoC容器感興趣。

我認爲我的場景應該是相當常見的,但我不確定,我不想浪費我的時間,試圖將一個方形的釘子插入圓孔,所以這裏是我的問題。任何/所有的IoC容器可以做到這一點嗎?如果沒有,你可以指向我的重構,這將改善我的代碼,並使IoC工作?

回答

1

Autofac肯定做您所需要的 - 明確規定參數可與由容器自動裝配組合:

vm = container.Resolve<SubFrameViewModel>(new NamedParameter("subframe", subframe)); 

(按類型而不是名稱匹配也是可能的。)

你甚至可以有容器注入Func鍵或自定義委託到調用組件,使容器的依賴(即調用解決)是不必要的:

Func<ISubFrame, SubFrameViewModel> _vmFactory; // Injected 
vm = _vmFactory(subframe); 

有關信息見http://code.google.com/p/autofac/wiki/DelegateFactories後者。

尼克

+0

嗯會誤解你的問題在二讀 - 反正HTH! – 2009-11-19 21:13:07

+0

無論這是否完全回答了我的所有問題,現在我指出了正確的方向。我可以肯定地看到,我可以如何使這一切更乾淨地工作。謝謝您的幫助。 – 2009-11-20 14:03:48

+0

看着Autofac文檔,它看起來像我是否爲每個子幀創建了一個嵌套容器並將FrameController標記爲ContainerScoped,我所需要做的就是使用您在那裏指定子幀並滿足所有需求。這似乎是一個合理的事情嗎? – 2009-11-20 14:13:43

1

它看起來像你想處理您的IoC方案的額外構造函數的參數,我看到兩個選項:

1 - 創建一個簡單的構造這需要在一個子幀,並且暴露ImageViewModel和FrameControlViewModel公衆可設置的屬性,像這樣:

// assumes frameControlVM and imageVM have been constructed and are valid 
foreach (var subframe in movieFile) 
{ 
    var subframeVM = container.Resolve<SubframeViewModel>(subframe); 
    subframeVM.ImageVM = imageVM; 
    subframeVM.FrameControlVM = frameControlVM ; 
    Subframes.Add(subframeVM); 
} 

2 - 傳給你需要到IoC容器,它只是傳遞參數到SubframeVM構造函數中的參數:

// assumes frameControlVM and imageVM have been constructed and are valid 
foreach (var subframe in movieFile) 
{ 
    var subframeVM = container.Resolve<SubframeViewModel>(subframe, imageVM, frameControlVM); 
    Subframes.Add(subframeVM); 
} 

最終您選擇哪一個取決於您希望您的SubframeViewModel IoC解析器與其他虛擬機的緊密耦合程度。如果您imageVM和frameControlVMs需要自己的國際石油公司,你可以簡單地把它們連在一起:

// assumes frameControlVM and imageVM have been constructed and are valid 
foreach (var subframe in movieFile) 
{ 
    var frameControlVM = container.Resolve<FrameControlViewModel >(subframe); 
    var imageVM = container.Resolve<ImageViewModel>(subframe, frameControlVM); 
    var subframeVM = container.Resolve<SubframeViewModel>(subframe, imageVM, frameControlVM); 
    Subframes.Add(subframeVM); 
} 
+0

謝謝Micah,這真的有幫助。你在這裏使用哪個IoC容器? – 2009-11-20 14:05:01

+0

我不知道。 :) 幾年前,當我需要做動態程序集加載以及工廠風格的類實例化時,我推出了自定義程序。但是,對於我所做的大多數小型項目來說,通過外部配置實現可插入實例的好處對於我來說比編譯時檢查更有價值 - 而且我不喜歡提前在接口和抽象類中進行猜測;這是我爲重構保存的東西。 – micahtan 2009-11-21 00:34:52