如何从 MVVM 样式的模型接口创建视图模型
本文关键字:模型 接口 创建 视图 样式 MVVM | 更新日期: 2023-09-27 17:56:50
我使用的是视图模型优先方法,在某些模型中,我通过这样的接口公开其他模型:
public class ModelA : IModel {}
public class ModelB : IModel {}
// plus yet unknown additional models
public class ViewModelA : IViewModel
{
ViewModelA(ModelA model){}
}
// a model may have several possible view models that should be selectable somehow
public class ViewModelAVariant : IViewModel
{
ViewModelAVariant(ModelA model){}
}
public class ViewModelB : IViewModel {}
{
ViewModelA(ModelB model){}
}
public class ModelContainer
{
public IModel[] SubModels { get { return new IModel { new ModelA(), new ModelB()};}}
}
public class ViewModelContainer
{
private ModelContainer modelContainer;
public IViewModel[] SubModels
{
get
{
return modelContainer.SubModels.Select( sm => ToViewModel(sm)).ToArray();
}
}
private IViewModel ToViewModel(IModel model)
{
// what to insert here?
}
}
可能的解决方案
变式 1:
存储IViewModel
转换器的IModel
集合,并在 ViewModel 中使用它们。
private IDictionary<type,Func<IModel,IViewModel>> converters;
private IViewModel ToViewModel(IModel model)
{
return converters[model.GetType()](model);
}
优点:
- 模型
- 不必了解视图模型
- 可以选择视图模型
缺点:
- 如果没有合适的转换器,该过程可能会在运行时失败
变体 2:
interface IModel
{
IViewModel ToViewModel();
}
public class ModelA : IModel
{
// this enables view model selection
public ModelA(Func<ModelA,IViewModel> converter)
{
this.converter = converter;
}
private Func<ModelA,IViewModel> converter;
public IViewModel ToViewModel()
{
return converter(this);
}
}
优点:
- 可以选择视图模型
- 易于使用,不易滥用
缺点:
- 模型
- 必须了解视图模型
我正在寻找一种没有缺点的变体。
听起来像是AutoMapper的一个很好的用例。
基本上,您将创建一个配置,在最简单的情况下是:
Mapper.CreateMap<ModelA, ViewModelA>();
Mapper.CreateMap<ModelA, ViewModelAVariant<>();
Mapper.CreateMap<ModelB, ViewModelB>();
这假定所有属性的名称都相同(在视图模型和模型中)。它还可以扁平化属性,即 按照惯例,ModelA.Property
被映射为ModelAProperty
是否存在。
如果您有更复杂的映射,则必须配置映射。
然后通过以下方式解决
ModelA modelA = ... // retrieve ModelA
ViewModelA viewModelA = Mapper.Map<ViewModelA>(modelA);
对于变体:
ModelA modelA = ... // retrieve ModelA
ViewModelAVariation viewModelA = Mapper.Map<ModelA, ViewModelAVariation>(modelA);
不过,您不应该以其他方式使用它,至少不建议从ViewModel转换为域/业务模型。它的主要目标是模型到DTO(数据传输对象)或模型到视图模型的映射。