Mvvm 我应该在容器中注册ViewModels吗?
我应该在容器中注册ViewModels并从中解析吗 好处:Mvvm 我应该在容器中注册ViewModels吗?,mvvm,dependency-injection,autofac,caliburn,Mvvm,Dependency Injection,Autofac,Caliburn,我应该在容器中注册ViewModels并从中解析吗 好处: 激活视图模型时,我可以执行一些操作 容器将为我注入依赖项 缺点: ViewModel生命周期管理可能很棘手: 如果将ViewModel设置为singleton,则无法实例化同一类型的多个控件 如果我将ViewModel设置为瞬态,那么当我实际期望注入同一个实例时,我很容易就会遇到具有多个不同实例的情况 正确答案是什么? 如果我能减轻终身缺点,我宁愿注册 如果有必要,我会使用Caliburn和Autofac。2)的好处足以让容器处
- 如果将ViewModel设置为singleton,则无法实例化同一类型的多个控件
- 如果我将ViewModel设置为瞬态,那么当我实际期望注入同一个实例时,我很容易就会遇到具有多个不同实例的情况
除此之外,还有其他情况下您希望在多个视图之间共享一个viewmodel实例吗?不确定autofac或Caliburn(可能仍然适用),但当它进入Unity容器时,我将仅在以下情况下注册viewmodel 当容器被处理掉的时候,我需要把它处理掉。您可以创建一个生命周期管理器来存储新创建的(非单例)视图模型实例
container.RegisterType<MyViewModel>(new DisposeableInstanceLifetimeManager());
...
container.Resolve<MyViewModel>(); // here all dependencies will get injected
...
container.Dispose();
container.RegisterType(新的DisposableInstanceLifeTimeManager());
...
container.Resolve();//这里将注入所有依赖项
...
container.Dispose();
如果您想共享数据,我倾向于创建一个子(子)容器,并将模型注册为单例,让多个视图模型共享同一个模型
var child = container.CreateChildContainer();
child.RegisterInstance(model, new ContainerControlledLifetimeManager());
child.Resolve<MyViewModel1>();
child.Resolve<MyViewModel2>(); // both can share the model instance
var child=container.CreateChildContainer();
RegisterInstance(model,newcontainerControlledLifetimeManager());
child.Resolve();
child.Resolve();//两者都可以共享模型实例
(注意:使用Unity时,在ViewModel上使用Resolve
时,即使未向容器注册,也会注入所有依赖项)
否则,除非您需要一个单例ViewModel(尽管我想不出什么时候它会有用),否则我觉得将ViewModel添加到容器中只会添加更多代码,没有任何好处。容器是一个由它创建的对象所占据的生态系统。视图模型与这些居民交互,因此也是生态系统的一部分。为了准确反映这种关系,您应该在容器中注册视图模型 您应该始终对视图模型使用
InstancePerDependency
。视图模型表示特定UI的状态和行为-它是控件的非特定框架的类似物。正如通常不能将同一控件实例放在UI树中的两个位置一样,也不能重用同一视图模型实例
如果可以,我们将其称为
ViewsModel
:-)当一个ViewModel需要注入到其他几个视图模型中时,情况如何?最简单的例子-状态栏。假设窗口上有几个控件(由多个视图模型支持),并且它们中的每一个都会在状态栏中不断更新消息。关于使用VIEWMDEST同时返回多个控件,请考虑网格,当您选择要查看详细信息的行时。当前行和详细信息控件很可能绑定到同一视图模型,只是显示方式不同而已。不过我喜欢你的第一段@Konstantin Spirin:对于状态栏,您将拥有一个实现视图模型之间通信的共享服务,而不是直接共享视图模型(@Peter Lillevold也建议了这一点)。对于网格/行示例,我几乎总是为行创建一个视图模型,为“详细信息”对话框创建一个单独的视图模型。它们可能都使用相同的实体实例,但具有不同的配置文件和意图,例如行上的编辑命令和对话框上的保存/取消命令。@Konstantin Spirin:我刚刚意识到您建议将StatusBarViewModel
注入StatusBarService
。我的建议正好相反:IStatusContext
将是两个视图模型之间的通信点,但它并不引用视图模型本身。因此,StatusBarViewModel
只需要解决一次,避免了这些问题。每个选项卡都包含报表,所有报表都应使用相同的日期选择器。你将如何实现这一要求?@康斯坦丁-我会考虑这样的观点作为几个视图(与相应的VIEW模型)。一个视图/模型表示处理选定日期的整个窗口,然后每个选项卡一个视图/模型。使用数据绑定,您可以轻松地将主视图中的SelectedDate绑定到每个子视图上的属性。应用程序的主窗口是singleton的最佳候选对象。主窗口通常包含在整个应用程序中共享的元素。例如,状态栏。使用Unity时,我做了非常类似的事情,但很容易迷失方向,因为您需要考虑注册哪个ViewModel,不注册哪个ViewModel。另外,将ViewModel作为依赖项是非常可怕的,因为Unity可以创建新实例,即使您还没有注册它。