AutoMapper - 映射到派生对象取决于条件

时间:2017-10-02 13:40:48

标签: c# automapper automapper-6

我想将源类映射到派生(从抽象)目标类依赖于某些属性的值。

我有以下源类:

public partial class ApplicationDriver
{
    public virtual ICollection<ApplicationDriverEquipment> Equipments { get; set; }

}

public partial class ApplicationDriverEquipment
{
    public int Id { get; set; }
    [StringLength(256)]
    public string Make { get; set; }
    [StringLength(256)]
    public string Model { get; set; }
    [StringLength(256)]
    public string Year { get; set; }
    [StringLength(256)]
    public string VINNumber { get; set; }
    [StringLength(256)]
    public string PlateNumber { get; set; }
    [StringLength(256)]
    public string CurrentMileage { get; set; }
    [StringLength(256)]
    public string Length { get; set; }
    public string Type { get; set; }

    public int DriverId { get; set; }
    public virtual ApplicationDriver Driver { get; set; }
}

我想映射到以下类,取决于Type参数:

public class ApplicationDriverDomain
{
    public List<ApplicationDriverEquipmentAbstractDomain> Equipments { get; set; }

}

public abstract class ApplicationDriverEquipmentAbstractDomain
{
    public int Id { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
    public string Year { get; set; }
    public string PlateNumber { get; set; }
    public string CurrentMileage { get; set; }
    public string Type { get; protected set; }
}

public class ApplicationDriverEquipmentTractorDomain : ApplicationDriverEquipmentAbstractDomain
{
    public ApplicationDriverEquipmentTractorDomain()
    {
        Type = ApplicationDriverEquipmentTypeStaticStringsDomain.Tractor;
    }
    public string VINNumber { get; set; }
}

public class ApplicationDriverEquipmentTrailerDomain : ApplicationDriverEquipmentAbstractDomain
{
    public ApplicationDriverEquipmentTrailerDomain()
    {
        Type = ApplicationDriverEquipmentTypeStaticStringsDomain.Trailer;
    }

    public string Length { get; set; }
}

public class ApplicationDriverEquipmentStraightTruckDomain : ApplicationDriverEquipmentAbstractDomain
{
    public ApplicationDriverEquipmentStraightTruckDomain()
    {
        Type = ApplicationDriverEquipmentTypeStaticStringsDomain.StraightTruck;
    }

    public string VINNumber { get; set; }
    public string Length { get; set; }
}

public class ApplicationDriverEquipmentCargoVanDomain : ApplicationDriverEquipmentAbstractDomain
{
    public ApplicationDriverEquipmentCargoVanDomain()
    {
        Type = ApplicationDriverEquipmentTypeStaticStringsDomain.CargoVan;
    }

    public string VINNumber { get; set; }
    public string Length { get; set; }
}

我尝试这样做:

    ApplicationDriverEquipmentAbstractDomain GetEquipment(Infrastructure.Asset.ApplicationDriverEquipment infrastructure)
    {
        ApplicationDriverEquipmentAbstractDomain result = null;
        var config = new MapperConfiguration(cfg => cfg.AddProfile<AutoMapperApplicationModel>());
        var mapper = config.CreateMapper();

        switch (infrastructure.Type)
        {
            case ApplicationDriverEquipmentTypeStaticStringsDomain.Tractor:
                result = mapper.Map<ApplicationDriverEquipmentTractorDomain>(infrastructure);
                break;

            case ApplicationDriverEquipmentTypeStaticStringsDomain.Trailer:
                result = mapper.Map<ApplicationDriverEquipmentTrailerDomain>(infrastructure);
                break;

            case ApplicationDriverEquipmentTypeStaticStringsDomain.StraightTruck:
                result = mapper.Map<ApplicationDriverEquipmentStraightTruckDomain>(infrastructure);
                break;

            case ApplicationDriverEquipmentTypeStaticStringsDomain.CargoVan:
                result = mapper.Map<ApplicationDriverEquipmentCargoVanDomain>(infrastructure);
                break;

        }

        return result;
    }

        CreateMap<Infrastructure.Asset.ApplicationDriverEquipment, ApplicationDriverEquipmentTractorDomain>();
        CreateMap<Infrastructure.Asset.ApplicationDriverEquipment, ApplicationDriverEquipmentTrailerDomain>();
        CreateMap<Infrastructure.Asset.ApplicationDriverEquipment, ApplicationDriverEquipmentStraightTruckDomain>();
        CreateMap<Infrastructure.Asset.ApplicationDriverEquipment, ApplicationDriverEquipmentCargoVanDomain>();

        CreateMap<Infrastructure.Asset.ApplicationDriverEquipment, ApplicationDriverEquipmentAbstractDomain>()
            .Include<Infrastructure.Asset.ApplicationDriverEquipment, ApplicationDriverEquipmentTractorDomain>()
            .Include<Infrastructure.Asset.ApplicationDriverEquipment, ApplicationDriverEquipmentTrailerDomain>()
            .Include<Infrastructure.Asset.ApplicationDriverEquipment, ApplicationDriverEquipmentStraightTruckDomain>()
            .Include<Infrastructure.Asset.ApplicationDriverEquipment, ApplicationDriverEquipmentCargoVanDomain>()
            .ForMember(dest => dest.Type, opt => opt.ResolveUsing(GetEquipment))
            ;

        CreateMap<Infrastructure.Asset.ApplicationDriver, ApplicationDriverDomain>()
            .ForMember(dest => dest.Equipments, opt => opt.MapFrom(src => src.Equipments));

但是我收到了一个错误:

  

&#34;错误映射类型。\ r \ n \ r \ n映射类型:\ r \ n \ nApplicationDriver - &gt;   ApplicationDriverDomain \ r \ nInfrastructure.Asset.ApplicationDriver - &gt;   Domain.POCO.Application.ApplicationDriverDomain \ r \ n \ r \ nType Map   配置:\ r \ nApplicationDriver - &gt;   ApplicationDriverDomain \ r \ nInfrastructure.Asset.ApplicationDriver - &gt;   Domain.POCO.Application.ApplicationDriverDomain \ r \ n \ r \ n属性:\ r \ nEquipments&#34;

2 个答案:

答案 0 :(得分:0)

<强>更新

所以我相信我理解你要做的事情,并且道歉我可能会稍微引导你走错路线。您的流程基本上是为了区分源对象的基础结构类型,然后创建该类型的对象。您还需要了解两种不同的Mapper设置方法。

在代码的第一部分中,您尝试使用Mapper的实例进行设置,然后使用我的静态样式使用Mapper.Map我建议始终使用静态样式,以便您有能力做一些更动态的方法来提取映射配置文件。

Mapper.Initialize(cfg => cfg.AddProfile<AutomapperRules>());
var domain = Mapper.Map<Domain.ApplicationDriverEquipmentTractorDomain>(inf);

接下来,您只需要引用从基础源到您的配置文件中的域类型的映射类型,即

CreateMap<ApplicationDriverEquipmentInfrastructure, ApplicationDriverEquipmentTractorDomain>();
CreateMap<ApplicationDriverEquipmentInfrastructure, ApplicationDriverEquipmentTrailerDomain>();
CreateMap<ApplicationDriverEquipmentInfrastructure, ApplicationDriverEquipmentStraightTruckDomain>();
CreateMap<ApplicationDriverEquipmentInfrastructure, ApplicationDriverEquipmentCargoVanDomain>();

然后你需要做的是从描述ApplicationDriver的映射中调用你的GetEquipment方法,即

CreateMap<ApplicationDriver, ApplicationDriverDomain>()
            .ForMember(dest => dest.Equipments, opt => opt.ResolveUsing(x => x.Equipments.Select(GetEquipment)));

private ApplicationDriverEquipmentAbstractDomain GetEquipment(ApplicationDriverEquipmentInfrastructure infrastructure)
    {
        switch (infrastructure.Type)
        {
            case "Tractor":
                return Mapper.Map<ApplicationDriverEquipmentTractorDomain>(infrastructure);
            case "Trailer":
                return Mapper.Map<ApplicationDriverEquipmentTrailerDomain>(infrastructure);
            case "StraightTruck":
                return Mapper.Map<ApplicationDriverEquipmentStraightTruckDomain>(infrastructure);
            case "CargoVan":
                return Mapper.Map<ApplicationDriverEquipmentCargoVanDomain>(infrastructure);
        }
        return null;
    }

示例用法:

Mapper.Initialize(cfg => cfg.AddProfile<AutomapperRules>());

var inf = new ApplicationDriverEquipmentInfrastructure()
{
     CurrentMileage = "mil",
     Length = "123",
     Make = "ccc",
     Model = "15",
     Type = "Tractor",
     VINNumber = "vin"
};

var driver = new ApplicationDriver()
{
     Equipments = new List<ApplicationDriverEquipmentInfrastructure>() {inf}
};

var domain = Mapper.Map<ApplicationDriverDomain>(driver);

答案 1 :(得分:0)

AM中的继承通过检查源的类型而不是使用鉴别器来工作。这就是你应该从文档中理解的内容。解决问题的一种方法是将现有目标传递给Map。由smth创建,就像GetEquipment方法一样。 ApplyBaseMapping是一个hack,您使用Include / IncludeBase重用配置。不幸的是,您还遇到了MyGet版本中已修复的错误,因此真正的错误对您来说是隐藏的。在您的版本中调试此问题的唯一方法是选中the execution plan