6

我正在使用 MVVM 模式开发 WPF 应用程序。我正在使用 MVVM Light 库,并且我也在尝试使用依赖注入器(我正在考虑 Ninject 和 Unity)。

我已经阅读了很多博客文章,我对让我的班级相互交流的“正确”方式感到很困惑。特别是,我不知道什么时候使用依赖注入,什么时候依赖中介模式。

让我们考虑一个例子。我有一个 ViewModel,我们称之为 DataViewModel,以及提供某种数据的 Data 类。他们之间如何更好地沟通:

A. 使用 IData 接口注入对 DataViewModel 的依赖?这样 Data 就不必依赖 Messenger,但如果 Data 发生变化,它必须提供一个事件,并且 ViewModel 必须订阅它。

B. 依赖中介者模式(在 MVVM Light as Messenger 中实现),在 Model 和 ViewModel 之间发送消息?这种方式根本不需要使用依赖注入,因为整个通信将基于消息。

此外,我的 ViewModel 是否应该在其他 ViewModel 上注入依赖关系,还是仅仅依赖 Messenger 会更好?如果是第一个,是否有必要为每个 ViewModel 定义一个单独的接口?我认为为每个 VM 定义一个接口将是一项额外的工作,但也许值得。

4

2 回答 2

4

通常,ViewModel 会转到 Service(正如 Prism 所说的那样)来检索它需要的数据。该服务通过 DI(构造函数注入)推送到 ViewModel,尽管您可以通过 ServiceLocator 以另一种方式执行此操作。

因此,您的 ViewModel 将持有对服务的引用,该服务将抽象您的数据检索。数据可能来自 DB、XML 文件,谁知道呢……抽象就在那里。因此,对于您的 IData 情况,对该类型的引用将在 ViewModel 中的某个点发生,但不会通过 DI 的任何方式发生。如果您的 IoC 框架允许(Prism 允许),您可以创建接口类型到具体类型的映射,然后通过容器检索这些类型;Unity就是这种情况。

这是一个简短的示例...脚本绑定到视图,并将 ViewModel 注入到视图中。请注意使用 IScriptService 检索数据。返回的数据是 IScript 类型的集合,但是我们从未将该类型正式注入到 ViewModel 中,因为我们不关心作为单个实体的类型,而是在更大范围内关心类型。

        public ScriptRepositoryViewModel(IUnityContainer container, IScriptService scriptService, IEventAggregator eventAggregator)
        {
            _container = container;
            _scriptService = scriptService;
            _eventAggregator = eventAggregator;
        }

        public ICollectionView Scripts
        {
           get 
           {
               if (_view == null)
               {
                   _view = CollectionViewSource.GetDefaultView(_scriptService.Scripts);
                   _view.Filter = Filter;
               }

               return _view;
           }
       }

当您进入视图时,可能会出现相同的情况,视图将通过 DI(构造函数注入)与 ViewModel 一起注入。我不会让其他 ViewModel 相互依赖,让它们保持隔离。如果您开始看到需要耦合,请查看您尝试共享的数据,通常需要进一步抽象数据,而不是与任何 ViewModel 耦合。

于 2010-11-17T18:20:17.483 回答
2

您的问题有不止一种好的解决方案,

我建议你在你的数据模型中使用一些单一的接口,把它放在一个基类中,这个接口将允许你的数据对象与外界通信。

对于视图模型注入的不是数据而是一个可以为您检索数据的接口,数据将公开事件,vm 在获取它们后可以向它们注册。

数据对象不应该知道谁持有他,视图模型知道他持有什么样的数据,但由于灵活性问题我不建议注入这些数据。

于 2010-11-17T18:16:32.720 回答