在我的应用程序(基于MVVM架构的WPF应用程序)中,我使用了很多ICommand
作为服务。其中一些命令可以绑定到菜单项,工具栏,状态栏等,它们被注入到相应的容器视图模型中。现在,其中一些例如能够操作应用程序的 Shell 上的数据,因此 Shell 是它们的依赖项。由于 Shell 还托管所述容器(菜单,状态栏......),因此我获得了循环依赖。 (Shell - > Menu - > Command - > Shell)。
目前,我使用MEF来编写我的应用程序,因此大多数时候问题可以通过属性或私有成员注入来解决,但我感觉这是一种令人讨厌的做法(服务无法告诉它需要这种依赖关系的父级,即使它确实如此)。
我的问题是:解决这样一个问题的常用方法是什么:
class Shell : IShell
.ctor(IMenu)
class Menu : IMenu
.ctor(ICommand[])
class ExitCommand : ICommand
.ctor(IShell)
答案 0 :(得分:1)
我从未使用过MEF,但确实使用了依赖注入容器,并遇到了类似的问题。问题是,(我认为)你将Shell作为一项服务(提供退出功能),但它也充当了ViewModel(显示菜单等)。它承担了更多责任。
让我们将你的“IShell”接口拆分为单独的模块,以证明:
class Shell : IShell, IExitManager
.ctor(IMenu)
class Menu : IMenu
.ctor(ICommand[])
class ExitCommand : ICommand
.ctor(IExitManager)
你的shell一次做两件事,它是ViewModel的东西(IShell),它正在管理退出(IExitManager)。
我要做的是从ViewModel中抽象出功能。我将创建一个专用的IExitManager
服务。而不是使ShellViewModel
实现此功能,并将整个事物注入仅需要触发退出事件的位置(拖动菜单功能并导致循环依赖性),而不是在专用{{1}中具有该功能}}
而不是你当前的:
而是将服务从Shell实现中移除:
您的类IExitManager
需要公开与您目前在IShell中使用的相同功能(我假定IExitManager
方法)和一个事件处理程序Exit()
,以便您的Shell监听并执行这是行动。
EventAggregator基本上是一个更通用的版本 - 我建议你看一下。您可以让Shell侦听EventExit事件,并发出命令。唯一的常见依赖是EventAggregator服务。这个解决方案的作用是仅针对Exit事件的“一次性”版本。如果您这样做很多,请使用EventAggregator。