【问题标题】:Automapper one source multiple destinations and derived classesAutomapper 一源多目的地和派生类
【发布时间】:2018-03-07 11:50:04
【问题描述】:

我正在尝试将一个实体对象映射到不同的视图模型。我有一个基础视图模型和其他两个从基础派生的视图模型。视图模型是通过工厂方法在运行时基于它们的类型属性创建的。派生视图模型没有单独的实体,源实体具有派生视图模型的所有属性。问题是 Automapper 能够通过工厂方法创建正确的对象,但派生对象中的属性根本没有映射。仅映射基本视图模型的属性。

示例实体:

public class VehicleEntity
{
    public int Type { get; set; }
    public int LoadCapacity { get; set; }
    public TrailerEntity Trailer { get; set; }
}

public class TrailerEntity
{
    public int Capacity { get; set; }
}

查看模型:

public class VehicleVM
{
    public int Type { get; set; }
}

public class CarVM: VehicleVM
{
    public TrailerVM Trailer { get; set; }
}

public class TruckVM : VehicleVM
{
    public int LoadCapacity { get; set; }
}

public class TrailerVM
{
    public int Capacity { get; set; }
}

public static class VehicleFactory
{
    public static VehicleVM GetInstance(int type)
    {
        switch (type)
        {
            case 1:
                return new CarVM();
            case 2:
                return new TruckVM();
            default:
                return new VehicleVM();
        }
    }
}

最后是映射:

        List<VehicleEntity> vehicleList = new List<VehicleEntity>();
        vehicleList.Add(new VehicleEntity()
        {
            Type = 1,
            LoadCapacity = 0,
            Trailer = new TrailerEntity()
            {
                Capacity = 120
            }
        });

        vehicleList.Add(new VehicleEntity()
        {
            Type = 2,
            LoadCapacity = 8000,
            Trailer = null
        });

        var config = new MapperConfiguration(cfg =>
        {
            cfg.CreateMap<VehicleEntity, VehicleVM>()
                .ConstructUsing((Func<VehicleEntity, VehicleVM>)(rc => VehicleFactory.GetInstance(rc.Type)))
                .Include<VehicleEntity, TruckVM>()
                .Include<VehicleEntity, CarVM>();
            cfg.CreateMap<VehicleEntity, TruckVM>();
            cfg.CreateMap<VehicleEntity, CarVM>();
            cfg.CreateMap<TrailerEntity, TrailerVM>();
        });

        IMapper mapper = config.CreateMapper();
        var vehicleVMs = mapper.Map<List<Data.VehicleEntity>, List<VehicleVM>>(vehicleList);

在上面的示例中,只有 Type 属性映射到 CarVM 和 TruckVM。其他属性不是...我也尝试使用 ForMember 方法来映射来自源实体的派生类属性,但没有运气。

cfg.CreateMap<VehicleEntity, TruckVM>().ForMember(dst => dst.LoadCapacity, opt => opt.MapFrom(src => src.LoadCapacity));

有可能实现吗?

【问题讨论】:

  • 这样不行。见here
  • 这里没有看到继承。确保这接近于minimal reproducible example
  • @HenkHolterman 抱歉。我已经更新了我的问题。该问题与 automapper 无法映射派生类中的任何属性有关。
  • TrailerEntity 有基类吗?
  • 真的去写那个minimal reproducible example

标签: c# inheritance automapper derived-class


【解决方案1】:

您可以使用以下配置

var config = new MapperConfiguration(
    cfg =>
    {
        cfg.CreateMap<VehicleEntity, VehicleVM>()
            .ConstructUsing(rc => VehicleFactory.GetInstance(rc.Type))
            .BeforeMap((s, d, c) => c.Mapper.Map(s, d));

        cfg.CreateMap<VehicleEntity, TruckVM>();
        cfg.CreateMap<VehicleEntity, CarVM>();
        cfg.CreateMap<TrailerEntity, TrailerVM>();
    });

在这种情况下,ConstructUsing 根据 Type 属性创建适当的目标对象,然后在 BeforeMap 中将源 VehicleEntity 实例映射到创建的目标对象。您也可以在 AfterMap 方法中进行。

或者您可以立即在ConstructUsing中创建目标对象并在其上映射源

var config = new MapperConfiguration(
    cfg =>
    {
        cfg.CreateMap<VehicleEntity, VehicleVM>()
            .ConstructUsing((rc, context) => context.Mapper.Map(rc, VehicleFactory.GetInstance(rc.Type)));

        cfg.CreateMap<VehicleEntity, TruckVM>();
        cfg.CreateMap<VehicleEntity, CarVM>();
        cfg.CreateMap<TrailerEntity, TrailerVM>();
     });

【讨论】:

  • 这就是我一直在寻找的。工作精美。谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-11-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多