【问题标题】:Mapping back Viewmodels to Models将视图模型映射回模型
【发布时间】:2014-04-21 15:54:43
【问题描述】:

在我的 N 层 DDD 架构中,我在应用层中的所有 ViewModel 类都实现了以下接口:

public interface IViewModel
{
    ModelEntitySuperType ToModel();
}

所以每个ViewModel 都知道如何映射回Domain Object(通过实现ToModel() 方法)。

[更新]

另外我在我的应用层使用了CQRS模式,所以我定义了下面的通用抽象类来实现Update命令,你可以在下面的类中看到ToModel()方法的用法(Handle方法):

public abstract class UpdateCommandHandler<TCommandParameter, TViewModel, TEntity> : ICommandHandler<TCommandParameter>
    where TCommandParameter : UpdateCommandParameter<TViewModel>
    where TViewModel : class, IViewModel, new()
    where TEntity : ModelEntitySuperType, IAggregateRoot, new()
{
    private readonly IRepository<TEntity> _repository;

    public string Code { get; set; }

    protected UpdateCommandHandler(IRepository<TEntity> repository, string commandCode)
    {
        Code = commandCode;
        _repository = repository;
    }

    public void Handle(TCommandParameter commandParameter)
    {
        var viewModel = commandParameter.ViewModelEntity;
        var entity = viewModel.ToModel() as TEntity;
        _repository.Update(entity);
    }

}

将映射逻辑放入ViewModel 对象是正确的方法吗? 实现这一目标的更好方法是什么?

【问题讨论】:

    标签: c# mapping viewmodel cqrs


    【解决方案1】:

    通常我在进行映射的层中有映射逻辑。因此,我让实体和视图模型彼此不知道,他们有单一的责任。数据类型之间映射的责任归于映射库(例如AutoMapper)或扩展方法。

    例如如果您想将Person 实体转换为PersonViewModel,那么使用 AutoMapper 它将看起来像

     var viewModel = Mapper.Map<PersonViewModel>(person);
    

    或者你可以有扩展方法

     public static PersonViewModel ToViewModel(this Person person)
     {
         // create view model and map its properties manually
     }
    

    用法看起来像您当前的代码,除了您不需要将ModelEntitySuperType 转换为PersonViewModel:

     var viewModel = person.ToViewModel();
    

    【讨论】:

    • 谢谢谢尔盖,我更新了这个问题。如果我想使用 Auto-mapper 来映射,我应该将 var entity = viewModel.ToModel() as TEntity; 替换为 var entity = AutoMapper.Mapper.Map&lt;ModelEntitySuperType&gt;(viewModel) as TEntity; 吗?我在代码中直接使用Automapper 是否正确,或者我应该定义一个 IObjectMapper 接口并将其注入到我的 CommandHandler 中吗?你能用代码指导我吗?
    • @Masoud 如果您在 AutoMapper 中配置了从 TypeA 到 TypeB 的映射,那么您可以创建 UpdateCommandHandler&lt;TParameter, TypeA, TypeB&gt; 并使用 Mapper.Map&lt;TypeB&gt;(instanceOfTypeA) 映射类型
    • 但我不想更改UpdateCommandHandler&lt;TCommandParameter, TViewModel, TEntity&gt; 的定义。因为如果我将其更改为您所说的,我必须为每个实体类型创建单独的 UpdateCommandHandler 类。例如UpdateCommandHandler&lt;TCommandParameter,CustomerView,Customer&gt;, ....因此,在当前对UpdateCommandHandler&lt;TCommandParameter,TViewModel,TEntity&gt; 的定义下,我应该将 IObjectMapper 之类的东西注入到我的命令处理程序中还是直接在 Handle 方法中使用 Automaper?
    • @Masoud 抱歉,我从未说过要更改 UpdateCommandHandler 的定义
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    相关资源
    最近更新 更多