2017-01-04 39 views
1

在我的應用程序(基於MVVM架構的WPF應用程序)中,我使用了很多ICommand s作爲服務。其中一些命令可以綁定到菜單項,工具欄,狀態欄等,在那裏它們被注入到相應的容器視圖模型中。現在,它們中的一些例如能夠操作應用程序的Shell上的數據,所以Shell是它們的依賴關係。由於Shell也承載所述容器(菜單,狀態欄...),我得到一個循環依賴。 (Shell - > Menu - > Command - > Shell)。循環依賴和控制反轉 - 如何解決這些問題?

目前,我使用MEF編寫我的應用程序,所以大多數時候問題可以通過屬性或私人成員注入來解決,但我有這種感覺這是一種討厭的做法(服務沒有辦法告訴父母它需要這種依賴性,儘管它確實需要)。

我的問題是:什麼是要解決這樣的問題的常用方法:

class Shell : IShell 
    .ctor(IMenu) 

class Menu : IMenu 
    .ctor(ICommand[]) 

class ExitCommand : ICommand 
    .ctor(IShell) 
+0

從父視圖模型('Shell')調用命令或具有全局可用命令的兩種常見方法是'EventAggregator'實現('Prism'中的'PubSubEvent')或'CompositeCommand'(再次從'Prism' )。 – mechanic

+0

什麼是「殼」?你能更詳細地描述它嗎? – Joe

+0

@Joe外殼主要是一個視圖模型,它充當所有其他視圖組件的容器。 – artganify

回答

1

我從來沒有使用MEF,但不要使用依賴注入容器,並面臨着類似的問題。問題是,(我認爲)你把你的Shell作爲一個服務(提供退出的功能),但它也充當ViewModel(顯示菜單等)。它應該承擔更多的責任。

讓我們拆你的包羅萬象的「IShell的」接口爲單獨的模塊,以證明:

class Shell : IShell, IExitManager 
    .ctor(IMenu) 

class Menu : IMenu 
    .ctor(ICommand[]) 

class ExitCommand : ICommand 
    .ctor(IExitManager) 

你的外殼同時做兩件事情,這是視圖模型的東西(IShell的)和它的管理退出(IExitManager)。

我會做的是從您的ViewModel抽象功能。我會創建一個專用的IExitManager服務。而不是使ShellViewModel實現此功能,並將整個事件注入只需觸發退出事件(拖動菜單功能並導致循環依賴關係)的位置,而是在專用的IExitManager中使用該功能。

而不是當前的:

enter image description here

反而襯托出了殼牌執行的服務:

enter image description here

你的類IExitManager需要將當前公開相同的功能你在IShell中(我假定有一個Exit()方法)和一個事件處理程序ExitRequestedHandler,供Shell進行監聽和執行這是行動。

EventAggregator基本上是一個更通用的版本 - 我建議你看一看。您可以讓您的Shell偵聽EventExit事件,並使用您的命令發佈它們。唯一的共同依賴是EventAggregator服務。這個解決方案所做的只是一個「一次性」版本,僅用於退出事件。如果你這樣做了很多使用EventAggregator。