2010-11-17 94 views
6

我正在開發一個使用MVVM模式的WPF應用程序。我使用的是MVVM Light庫,我也試圖使用依賴注入器(我正在考慮Ninject和Unity)。MVVM:Model和ViewModels之間的通信

我讀過很多博客文章,對於讓我的課程相互交流的「正確」方式我很困惑。特別是,我不知道何時使用依賴注入以及何時依賴中介模式。

讓我們考慮一個例子。我有一個ViewModel,我們稱之爲DataViewModel,以及提供某種數據的Data類。 它們之間如何更好地進行通信:

A.通過IData接口向DataViewModel注入依賴項?這樣Data就不必依賴Messenger,但如果數據發生變化,它必須提供一個事件,並且ViewModel必須訂閱它。

B.依賴介體模式(在MVVM Light中以Messenger實現)並在Model和ViewModel之間發送消息?這樣就根本不需要使用依賴注入,因爲整個通信將基於消息。此外,我的ViewModels是否已經注入了其他ViewModel的依賴關係,還是隻依靠Messenger?如果第一個,是否有必要爲每個ViewModel定義一個單獨的接口?我認爲爲每個虛擬機定義一個接口將是一項額外的工作,但也許值得。

回答

4

一般來說,ViewModel轉到一個服務(如Prism調用它)來檢索它需要的數據。該服務通過DI(構造函數注入)被推送到ViewModel,儘管您可以通過ServiceLocator以另一種方式執行此操作。

因此,您的ViewModel將持有對服務的引用,該服務將抽象化您的數據檢索。數據可能來自數據庫,XML文件,誰知道......抽象就在那裏。因此,對於IData的情況,對該類型的引用將在ViewModel中的某個點發生,但不會以DI中的任何一種方式發生。如果您的IoC框架允許它(Prism),您可以創建接口類型到具體類型的映射,然後通過容器檢索這些類型; Unity就是這種情況。

這裏是一個簡單的例子...腳本綁定到View並且ViewModel被注入到View中。注意使用IScriptService來檢索數據。返回的數據是IScript類型的集合,但是我們從未正式將該類型注入到ViewModel中,因爲我們並不關心該類型作爲我們關心宏觀規模類型的單個實體。

 public ScriptRepositoryViewModel(IUnityContainer container, IScriptService scriptService, IEventAggregator eventAggregator) 
     { 
      _container = container; 
      _scriptService = scriptService; 
      _eventAggregator = eventAggregator; 
     } 

     public ICollectionView Scripts 
     { 
      get 
      { 
       if (_view == null) 
       { 
        _view = CollectionViewSource.GetDefaultView(_scriptService.Scripts); 
        _view.Filter = Filter; 
       } 

       return _view; 
      } 
     } 

當你用自己的方式查看,同樣的情況下,可曾有,查看將獲得通過DI(構造函數注入)與視圖模型注入。我不會讓其他ViewModel相互依賴,讓它們隔離。如果您開始看到耦合需求,請查看您嘗試共享的數據,然後經常需要將這些數據進一步抽象出來,而不是耦合到任何ViewModel。

+0

現在我明白了......但我需要一些時間來習慣依賴注入和服務:)謝謝! – madbadger 2010-12-07 14:29:36

1

有不止一個很好的解決你的問題,

我建議你使用一些單一界面的數據模型,把它放在一個基類,這個接口可以讓你的數據對象與溝通外面的世界。

對於視圖模型不注入數據,而是注入一個可以爲您檢索數據的界面,數據會暴露vm在獲取它們之後可以向其註冊的事件。

數據對象不應該知道誰擁有他,查看模型知道他擁有什麼樣的數據,但我不建議注入這些數據由於靈活性問題。