2015-06-05 36 views
3

註冊事件處理程序從硬件層傳播事件到數據層到UI層的推薦位置在哪裏?情況如下:使用ServiceLocator引導程序在MVVM應用程序中註冊事件處理程序的正確位置?

  • 在C#的應用/ .NET
  • MVVM圖案用於
  • 引導程序被實施,使用具有微軟統一框架實現的服務定位

簡化,有是三層,用匯編分隔:

  • UI.dll(UI層,包含ViewModel和View)
  • Data.dll(模型層)
  • HardwareAbstraction.dll(硬件層)

入口點是starter.exe,含有該引導程序和設置的ServiceLocator。其他庫使用該ServiceLocator。 UI.dll然後從ServiceLocator獲取數據接口。

在ViewModel中,需要顯示一些數據,數據一到達硬件即可。數據流是:掃描儀像硬件 - > HardwareAbstraction.dll - > Data.dll - > UI.dll。從一個DLL到下一個,會觸發一個事件通知監聽器新數據已到達。

在這些事件中註冊事件處理程序的最佳位置在哪裏?

在應用程序中,目前沒有真正的概念,很多是在構造函數中完成的,但它對我來說似乎不正確。讓他們在構造函數中,經常打破我的單元測試(在現有應用程序中引入單元測試)和設計時間ViewModels(使用C#而不是Xaml)。

回答

1

一般來說,我儘量避免使用全球服務定位器。我認爲這是一種反模式。不要在viewModels中使用它。它會使測試成爲一個熊。只需在構造函數中傳遞依賴關係即可。每個應用程序都有一個主IoC容器:我的主引導程序。然後我在一些工廠註冊的人少得多。我從不暴露容器。這個計劃是在多年的戰鬥中失蹤和過時的依賴。

viewModel級別應該使用PropertyChanged和ObservableCollection的東西來暴露它的事件。如果你能夠幫助,沒有人應該以編程方式註冊這些人;它們應該全部用於UI級別的綁定。硬件抽象只是模型級實體的另一種形式。它是(數據的來源)。您可以有多個數據/模型圖層。

在(viewModel或模型管理器)構造函數中註冊模型級事件是正確的。在Dispose中清理它們。我已經做了一件事,使其更清潔一點就是在有人註冊時在模型中觸發事件。它看起來像這樣:

class ModelManager: IModelManager { 
    ... 
    private Action<IModel> _modelAdded = delegate {}; 
    public event Action<IModel> ModelAdded { 
    add { 
     _modelAdded = Delegate.Combine(_modelAdded, value); 
     foreach(var model in Models) 
      value.Invoke(model); 
    } 
    remove { ... } 
    } 
    ... 
} 

class ModelManagerVM: ViewModelBase { 
    public ModelManagerVM(IModelManager mgr, IModelVMFactory factory) { 
     _factory = factory; 
     _mgr = mgr; 
     _mgr.ModelAdded += OnModelAdded; // triggers on subscribe 
    } 
    private void OnModelAdded(IModel model) { // never virtual 
     // use a dispatcher to push this to the UI thread 
     var existing = _modelVMs.FirstOrDefault(m => m.ID == model.ID); 
     if (existing != null) existing.Model = model; 
     else _modelVMs.Add(_factory.Create(model)); 
    } 
    public void Dispose() { 
     _mgr.ModelAdded -= OnModelAdded; // always unsubscribe on passed-in deps 
    } 
} 
相關問題