将viewmodel映射到使用TPH模式创建的模型

时间:2016-08-23 07:19:49

标签: asp.net-mvc automapper tph

我有一个基类和3个子类以及具有所有属性的单个viemodel。我希望在我的控制器中创建动作以将此视图模型绑定到具体的子类型。

这是我的创建操作,它不起作用(我正在获取错误映射类型):

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(AdViewModel vm)
{
    if (ModelState.IsValid)
    {
         var ad = Mapper.Map<Ad>(vm);
        _context.Ads.Add(ad);
        _context.SaveChanges();
         return RedirectToAction("Index");
    }
    return View();
}

这是自动配置:

Mapper.Initialize(config =>
        {
            config.CreateMap<AdViewModel, Ad>().ReverseMap();
            config.CreateMap<AdViewModel, Realty>().ReverseMap();
            config.CreateMap<AdViewModel, Auto>().ReverseMap();
            config.CreateMap<AdViewModel, Service>().ReverseMap();
        });

这是有效的代码,但我怀疑使用它:

public IActionResult Create(AdViewModel vm)
{
    if (ModelState.IsValid)
    {
        if (vm.RealtyType != null)
        {
            var ad = Mapper.Map<Realty>(vm);
            _context.Add(ad);
        }
        else if (vm.AutoType != null)
        {
            var ad = Mapper.Map<Auto>(vm);
            _context.Add(ad);
        }
        else
        {
            var ad = Mapper.Map<Service>(vm);
            _context.Add(ad);
        }
        _context.SaveChanges();
        return RedirectToAction("Index");
    }
    return View();
}

1 个答案:

答案 0 :(得分:0)

你必须把逻辑放在某处创建正确的子类。如果要在Automapper配置中隐藏它,可以通过定义构造函数来实现。这仅在目标实体相关时才有效(我将假设AdRealtyAutoService的基类。

// construct correct subtype of entity, depending on ViewModel state
var ctorFunc = new Func<AdViewModel, Ad>(vm => {
    if (vm.RealtyType != null) {
        return new Realty();
    }
    // etc.
});

// create correct subclass, map common properties of base class, 
// then dispatch to map properties of child class
CreateMap<AdViewModel, Ad>()
    // construct correct subclass of target entity
    .ConstructUsing(ctorFunc)
    // map common members to base class
    .ForMember(ent => ent.CommonField, o => o.MapForm(vm => vm.CommonField)
    // dispatch to mapping of child class
    // NOTE: this assumes that this profile was used to configure the static AutoMapper
    .AfterMap((vm, ent) => Mapper.Map(vm, ent, vm.GetType(), ent.GetType()));

// define rules for special members of child classes
CreateMap<AdViewModel, Realty>().ReverseMap();
// etc.

然后您应该能够成功致电var ad = Mapper.Map<Ad>(vm);