如何从 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);
    }
}

优点:

  • 可以选择视图模型
  • 易于使用,不易滥用

缺点:

    模型
  • 必须了解视图模型

我正在寻找一种没有缺点的变体。

如何从 MVVM 样式的模型接口创建视图模型

听起来像是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(数据传输对象)或模型到视图模型的映射。