MVVM框架:性能

4

我目前正在寻找我们下一个应用程序将使用的框架。目前我们有几个使用winform运行的应用程序,计划逐步转移到WPF(使用新应用程序,然后重构GUI)。我们是一个由9人组成的团队,致力于解决这个问题。

我们有一个大型解决方案(目前有300多个VS项目,约1,500,000行代码),因此在选择框架时,我们正在寻找一些可以促进清洁代码、良好基础架构的东西,同时又不会(太多)拖慢应用程序的框架。

目前,我主要对Prism(似乎有点难以完全理解)和Caliburn.Micro感兴趣。

Caliburn.Micro似乎更容易使用,但我有点担心所有那些基于约定的东西意味着很多事情都将在运行时使用Reflection完成。

我的理解正确吗?还是编译时就完成了?

另外,我不确定是否应该考虑MVVM Light,因为它缺乏文档/面向的应用程序大小。


MVVM并不需要快速运行,因为其操作往往不需要迭代。不用担心。就个人而言,我不喜欢传统的方法。 - Gusdor
你可以尝试使用MugenMvvmToolkit,它是一个跨平台框架,也支持WinForms。它非常适合大型项目。虽然文档不多,但有很多示例。如果您对该项目有任何问题,我将很乐意回答。 - Vyacheslav Volkov
你能提供一些示例(可能来自Caliburn.Micro文档),让你认为它会变慢吗?到目前为止,我只发现了使用反射/惯例的ViewModelLocator,这不是你应该担心的东西。 - Liero
例如:<ListBox x:Name="Products" /> 要绑定到 VM 的 "Product" 属性,这需要使用反射来获取属性,对吗? - J4N
好的,我之前并不知道这一点,也绝不会这样做,但这不应该是性能问题。如果是这样的话,没有人说你必须使用这种约定。但这就是我不喜欢 MVVM 框架的原因。你说你希望 MVVM 框架会强制或指导你和你的团队以正确的方式组织代码,但通常 MVVM 框架提供了太多的方式,因为它们必须支持每种可能的情况。通过编写自己的组件,如视图模型的基类、命令或导航服务,你可以更好地控制你的团队。 - Liero
然而,它需要一些MVVM经验以及某种写好API的才能,但这就是为什么我们称自己为技术架构师的原因,不是吗? :) - Liero
3个回答

11
首先,Prism不是一个MVVM框架。虽然有Prism.MVVM,但它是一个非常轻量级的MVVM库,并且与Prism无关。
其次,在Caliburn.Micro中自动数据绑定到viewmodel的<ListBox x:Name="Products" />不应该是性能问题,因为WPF中的普通Binding无论如何都使用反射。不确定Caliburn是否也在内部使用反射,但即使使用,如果不在迭代场景中进行(例如在具有1000多项的ItemsControl中),运行时几乎不会注意到。如果您遇到性能问题,则可以按照标准方式编写它。然而,这带来的附加价值是值得怀疑的。在我看来, 它带来的问题比解决的问题还要多。
如果能给你建议的话,不要使用任何MVVM框架。你只需要实现 INotifyPropertyChangedDelegateCommand (ICommand 实现)。在某些特殊情况下,您可能需要EventAggregator。现在告诉我,这三个类值得一个框架吗?不, 不值得。为什么要引入对第三方库的依赖呢?
如果您将要开始这样一个大型解决方案,编写自己的基础类库的投资微不足道。您总是可以从Prism中获取一个或两个类的源代码并将它们用于自己的库中。
这些框架的问题在于,开发人员倾向于过度设计简单的情况,例如在更适合使用普通事件甚至直接引用的场景中使用EventAggregator。以Prism为例,他们使用区域和视图注入,而可以使用简单的ItemsControl
经过6年WPF经验后,我成为ViewModel-First方法的支持者。然后MVVM变得更简单。但大多数框架使用View-First方法效果更好。
因此,我的建议是不要使用任何MVVM框架。如果必须使用一个,请选择Prism.MVVM。并查看源代码,它们写得很好。

我有这样的印象,使用框架将指导我们进行初始创建并给我们一个需要遵守的结构,这是一件好事,因为这是我们第一个使用WPF的“真正”的项目。关于大型项目:第一个应用程序将是一个小型应用程序,由于目标是说服管理层逐步迁移到WPF,如果他们看到第一个应用程序成本翻倍,我不确定他们会很高兴。当你说ViewModel优先时,你仍然是指“在模型/业务内容之后”吗? - J4N
所谓的“viewmodel-first”更多指的是视图和视图模型的生命周期,而不是开发方法。例如,请参考:http://stackoverflow.com/a/28916120/475727 它基本上是说,首先实例化视图模型,然后根据命名约定实例化视图。就这样。 - Liero
好的,我明白了。没想到它也用于导航。Caliburn采用这种方法,对吧?但是使用这种方法,如果我们为视图模型创建一个新视图,我们不能同时拥有两个并切换到新的视图,对吧? - J4N
这只适用于页面。但是,每个视图模型只有一个视图,反之亦然,是推荐的做法:http://practicalmvvm.com/Manifesto/ 这样做只会让事情变得更简单。您仍然可以使用继承来拥有类似的视图模型,并实现最大程度的代码重用。 - Liero
是的,我同意,我们只是暂时这样做,直到完全实现。但最终,我们很少这样做。 - J4N
显示剩余2条评论

1
我已经使用CM几年了,从1.1版本开始。 我从PRISM转过来。虽然我同意其他帖子中的一些评论和观点,但您在这个阶段真正的选择只是获取库/框架(无论您选择哪个),将其连接并在重要项目的空闲时间内运行一下。 在“付费时间”实施它可能不利于您,因为您肯定会在“实验”期间有问题。
先进行实验,然后再做决定。想要关注点分离?想要快速开发?想要能够将控件放在工作区上并命名,它就可以正常工作(假设它具有内置约定或为第三方控件创建自己的约定),将一些视图模型代码连接到您命名的控件的属性或方法,那么请尝试使用Caliburn.Micro。不想使用Caliburn的约定,那就不用。 CM的几乎所有内容都被模块化为核心需求,并通过Nuget安装。
有许多MVVM框架和库,它们都有不同的利基领域,有些是跨平台的,有些则针对某一平台。你只能使用自己尝试过的东西,最终如果你发现某个框架或库适合你和你的团队使用,并且它能够正常工作,那么就应该选择它。
我离开PRISM的原因示例:
在视图中: <Button x:Name="ClickMe" /> 在视图模型中:
public void ClickMe()
{
}

public string FirstName
{
  get{...}
  set
{
    _firstname = value;
    NotifyOfPropertyChange();
    NotifyOfPropertyChange( () => CanClickMe); )
}


public bool CanClickMe
{
    get { return !string.IsEmptyOrNull(_firstname); }
}

我很感谢这个反馈。是什么让你在 PRISM 之后转向 CM? - J4N
更新以显示为什么我离开 PRISM 的小片段,需要比上面的代码多两倍的代码,因为您需要创建一个带有 execute 和 canexecute 委托的 RelayCommand,然后传递必要的其他项,然后在视图中,您需要设置 IsEnabled 和 Command 属性。 - mvermef

0

大多数WPF性能问题不是由MVVM框架引起的,而是由您实现WPF应用程序的方式引起的(例如,您是否使用虚拟列表?)。我认为您应该根据功能需求选择MVVM框架(例如,是否提供所有功能,例如命令实现、视图模型基类等)。

更重要的是定义实现MVVM/WPF的约定和规则,并根据这些规则选择MVVM框架。一些约定和规则可以在我的文章中关于实现MVVM和XAML/.NET应用程序的建议和最佳实践中找到。

有很多关于选择正确的MVVM框架的资源,例如:


我知道这不是性能泄漏最重要的原因,但在我们选择使用哪个框架的平衡中,它仍然很重要。 我的问题只涉及性能,正是因为所有其他资源(我已经阅读过的)根本没有提到这一点。 - J4N
为了保险起见,你应该选择一个库(例如MVVM Light)而不是框架(Caliburn),因为库的干扰性较小,当应用程序的某个特定区域存在性能问题时,你仍然可以编写自己的代码并且不使用该库来解决这个问题... - Rico Suter
我使用了MVVM Light,并且很喜欢它,但是问题在于我无法找到任何文档、书籍或示例,展示了我可以使用哪些功能以及如何使用它们。 - J4N

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接