在我的应用程序(基于 MVVM 架构的 WPF 应用程序)中,我使用了很多 ICommand
s 作为服务。其中一些命令可以绑定(bind)到菜单项、工具栏、状态栏等,它们被注入(inject)到相应的容器 View 模型中。现在,它们中的一些例如能够在应用程序的 Shell 上操作数据,因此 Shell 是它们的依赖项。由于 Shell 还托管所述容器(菜单、状态栏...),因此我得到了循环依赖。 (外壳 -> 菜单 -> 命令 -> 外壳)。
目前,我使用 MEF 来编写我的应用程序,所以大多数时候问题可以通过属性或私有(private)成员注入(inject)来解决,但我觉得这是一种令人讨厌的做法(服务无法告诉 parent 它需要这种依赖,即使它确实如此)。
我的问题是:解决此类问题的常用方法是什么:
class Shell : IShell
.ctor(IMenu)
class Menu : IMenu
.ctor(ICommand[])
class ExitCommand : ICommand
.ctor(IShell)
最佳答案
我从未使用过 MEF,但确实使用了依赖注入(inject)容器并且遇到了类似的问题。问题是,(我认为)您将 Shell 作为服务扔掉(提供退出功能),但它也充当 ViewModel(显示菜单等)。它承担了本应承担的更多责任。
让我们将包罗万象的“IShell”接口(interface)拆分为单独的模块来演示:
class Shell : IShell, IExitManager
.ctor(IMenu)
class Menu : IMenu
.ctor(ICommand[])
class ExitCommand : ICommand
.ctor(IExitManager)
你的 shell 同时做两件事,它是 ViewModel 的东西 (IShell) 和它正在管理退出 (IExitManager)。
我要做的是从您的 ViewModel 中抽象出功能。我会创建一个专用的
IExitManager
服务。而不是制作 ShellViewModel
实现这个功能,并将整个东西注入(inject)到只需要触发退出事件的地方(拖动菜单功能并导致循环依赖),而是将该功能放在专用的IExitManager
中。 .而不是您当前的:
而是将服务带出 Shell 实现:
您的类(class)
IExitManager
将需要公开与您目前在 IShell 中拥有的相同功能(我假设是 Exit()
方法)和事件处理程序 ExitRequestedHandler
让您的 Shell 监听并执行它的操作。EventAggregator 基本上是一个更通用的版本——我建议你看一下。你可以让你的 Shell 监听 EventExit 事件,然后你的命令发出它们。唯一常见的依赖项是 EventAggregator 服务。该解决方案所做的是仅针对退出事件的“一次性”版本。如果您经常这样做,请使用 EventAggregator。
关于c# - 循环依赖和控制反转 - 如何解决这些问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41474188/