我进行了广泛的搜索,但未能找到关于如何使用具有多层视图模型的依赖注入来正确设计应用程序的任何好的指导。
[如果您有需要创建视图模型并且需要创建其他视图模型的视图模型,那么使用Unity之类的实现依赖注入的最佳方法是什么?
例如,假设我有一个带有MainViewModel的应用程序,我希望在其中可以在Visual Studio的选项卡式界面中显示一堆不同类型的数据。
我执行命令以使用称为UsersViewModel的视图模型打开User对象的集合。此视图模型在其构造函数中使用存储库IUserRepository。调用IUserRepository上的GetAll方法以获取用户对象的集合,这些对象显示在视图的网格中。
如果需要编辑特定User对象的详细信息,则需要创建一个UserViewModel,该类也接受IUserRepository的实例以及其构造函数中特定User对象的ID。调用IUserRepository上的FindById方法以获取特定的User对象。
我需要在主视图的单独选项卡中显示用户详细信息。我需要能够同时查看/编辑多个User对象的详细信息,因此我不能只以模态方式打开详细信息。因此,UserViewModel必须能够保留自己的更改,因为可以在保存特定的UserViewModel之前关闭UsersViewModel。
那么在这种情况下解决UserViewModel实例的最佳方法是什么?我可以将IUnityContainer的一个实例传递给UsersViewModel,然后使用该实例来解析它们,但是根据我的阅读,这是一个坏主意。还可以怎么做?
我已经用Autofac和MEF设置了MVVM应用程序,以解决您正在谈论的问题。长话短说,我创建了一个服务接口IViewModelProvider
,该接口为任意模型提供ViewModels。如果找不到特定模型的请求ViewModel类型的ViewModel,则此服务的实现为所有ViewModel提供缓存,并为模型创建ViewModel。
ViewModelProvider
是它自己的IoC容器,它在初始化时反映所有已加载的程序集,然后在运行时解析依赖项。 ViewModelProvider为服务IViewModelProvider
注册其自身的实例,因此可以将其自身传递给ViewModels
,这需要实例化新的ViewModels的能力。
我对此解决方案感到非常满意,因为我感觉这里的关注点很整洁。全局ViewModel缓存非常棒,因为它可以节省资源,并且您实际上可以比较ViewModels是否相等,这在我经常遇到。
如您在问题中指出的,可以通过使用与UI相同的IoC容器来简化此解决方案。我同意直接将IUnityContainer
传递给ViewModels不是一个好主意。但是,对于使用容器解析ViewModel而言,我看不到任何错误。我建议构建一个简单的服务,该服务可缓存ViewModel实例并使用IUnityContainer
创建新的ViewModel。
以下代码是伪代码,将一些MEF与一些Autofac语法混合在一起,但是我认为它的含义很清楚:
用于获取ViewModels的接口:
public interface IViewModelProvider
{
T GetViewModel<T>(object model);
}
导入Unity容器并将其用于解析尚未缓存的ViewModel的实现。 ViewModelCache
就像是您必须自己构建的高级词典。
[Export(typeof(IViewModelProvider))]
public class ViewModelProvider : IViewModelProvider
{
private IUnityContainer _container;
private ViewModelCache _viewModelCache;
[ImportingConstructor]
public ViewModelProvider(IUnityContainer container)
{
_container = container;
}
public T GetViewModel<T>(object model)
{
if (_viewModelCache.Contains<T>(model))
return _viewModelCache.Get<T>(Model);
var viewModel = _container.Resolve<T>();
viewModel.Model = model;
_viewModelcache.Cache(viewModel);
return viewModel;
}
}
然后可以将该服务注入您的ViewModels中,并且ViewModels可以创建自己的子ViewViews,而不必担心是否已经存在这些子视图,因为或需要创建它们。
希望这会有所帮助。这是一个广泛的主题,因此请询问您是否有任何特定问题。
Marc先生,您能否详细说明一下ViewModel Cache的概念?