循环依赖和控制反转 - 如何解决这些问题?

时间:2017-01-04 22:20:25

标签: c# wpf mvvm dependency-injection circular-dependency

在我的应用程序(基于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)

1 个答案:

答案 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}中具有该功能}}

而不是你当前的:

enter image description here

而是将服务从Shell实现中移除:

enter image description here

您的类IExitManager需要公开与您目前在IShell中使用的相同功能(我假定IExitManager方法)和一个事件处理程序Exit(),以便您的Shell监听并执行这是行动。

EventAggregator基本上是一个更通用的版本 - 我建议你看一下。您可以让Shell侦听EventExit事件,并发出命令。唯一的常见依赖是EventAggregator服务。这个解决方案的作用是仅针对Exit事件的“一次性”版本。如果您这样做很多,请使用EventAggregator。