3

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

我有以下源类:

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));

但我得到一个错误:

"错误映射类型。\r\n\r\n映射类型:\r\nApplicationDriver -> ApplicationDriverDomain\r\nInfrastructure.Asset.ApplicationDriver -> Domain.POCO.Application.ApplicationDriverDomain\r\n\r\n类型映射配置: \r\nApplicationDriver -> ApplicationDriverDomain\r\nInfrastructure.Asset.ApplicationDriver -> Domain.POCO.Application.ApplicationDriverDomain\r\n\r\n属性:\r\n设备"

4

2 回答 2

2

更新:

因此,我相信我理解您要做什么,并且很抱歉,我可能使您走错了路。您的流程基本上是区分源对象是什么基础设施类型,然后创建该类型的对象。您还需要了解两种不同的 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>();

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

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);
于 2017-10-02T15:04:15.833 回答
0

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

于 2017-10-05T08:08:53.727 回答