Automapper - 将上层 属性 作为参数传递给下层地图
Automapper - Passing an upper level property as a parameter to lower level map
我希望能够在注释映射部分访问 ShipmentIdentifier 属性,这样我就可以 运行 下面的断言语句成功。下面是我的映射器的简化版本。我如何在映射 WeightUnit 时传递 ShipmentIdentifier 属性?
using AutoMapper;
using System.Collections.Generic;
using Xunit;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
IMapper mapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(typeof(PrintLabelCommandMappingProfile));
}).CreateMapper();
CarrierLabelPrintedMessage message = new CarrierLabelPrintedMessage
{
ShipmentIdentifier = "AB1234",
Cartons = new List<Carton>
{
new Carton
{
TrackingNumber = "TestTrackingNumber",
LabelData =
new LabelData
{
Weight = 5,
WeightUnit = "none"
}
}
}
};
var command = mapper.Map<PrintLabelCommand>(message);
Assert.Equal(command.ShipmentUnits[0].Weight.Unit, WeightUnit.None);
}
public class PrintLabelCommandMappingProfile : Profile
{
public PrintLabelCommandMappingProfile()
{
CreateMap<CarrierLabelPrintedMessage, PrintLabelCommand>()
.ForMember(cmd => cmd.ShipmentId, exp => exp.MapFrom(msg => msg.ShipmentIdentifier))
.ForMember(cmd => cmd.ShipmentUnits, exp => exp.MapFrom(msg => msg.Cartons));
CreateMap<Carton, ShipmentUnit>()
.ForMember(su => su.Id, exp => exp.MapFrom(c => c.TrackingNumber))
.ForPath(su => su.Weight.Amount, exp => exp.MapFrom(c => c.LabelData.Weight))
.ForPath(su => su.Weight.Unit, exp => exp.MapFrom(c => c.LabelData.WeightUnit));
CreateMap<string, WeightUnit>().ConvertUsing((str, _) =>
{
// I want to have ShipmentIdentifier field to be accessible in the upper level to implement the mapping logic here as below
//if (ShipmentIdentifier.StartsWith("AB")) // it's "AB1234" in the sample
// return WeightUnit.None;
//else
return WeightUnit.Grams;
});
}
}
public class CarrierLabelPrintedMessage
{
public string ShipmentIdentifier { get; set; }
public List<Carton> Cartons { get; set; }
}
public class PrintLabelCommand
{
public string ShipmentId { get; set; }
public List<ShipmentUnit> ShipmentUnits { get; set; }
}
public class Carton
{
public string TrackingNumber { get; set; }
public LabelData LabelData { get; set; }
}
public class LabelData
{
public double Weight { get; set; }
public string WeightUnit { get; set; }
}
public class ShipmentUnit
{
public string Id { get; set; }
public Weight Weight { get; set; }
}
public class Weight
{
public double Amount { get; set; }
public WeightUnit Unit { get; set; }
}
public enum WeightUnit
{
None,
Grams,
Kilograms
}
}
}
有什么想法吗?
您可以在 CreateMap<CarrierLabelPrintedMessage, PrintLabelCommand>()
映射上使用 AfterMap()
,以根据 CarrierLabelPrintedMessage
中可用的信息“修复”映射。映射可能如下所示:
CreateMap<CarrierLabelPrintedMessage, PrintLabelCommand>()
.ForMember(cmd => cmd.ShipmentId, exp => exp.MapFrom(msg => msg.ShipmentIdentifier))
.ForMember(cmd => cmd.ShipmentUnits, exp => exp.MapFrom(msg => msg.Cartons))
.AfterMap((src, target) => {
WeightUnit targetValue = WeightUnit.Grams;
if (src.ShipmentIdentifier.StartsWith("AB"))
{
targetValue = WeightUnit.None;
}
foreach (ShipmentUnit shipmentUnit in target.ShipmentUnits)
{
shipmentUnit.Weight.Unit = targetValue;
}
});
我希望能够在注释映射部分访问 ShipmentIdentifier 属性,这样我就可以 运行 下面的断言语句成功。下面是我的映射器的简化版本。我如何在映射 WeightUnit 时传递 ShipmentIdentifier 属性?
using AutoMapper;
using System.Collections.Generic;
using Xunit;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
IMapper mapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(typeof(PrintLabelCommandMappingProfile));
}).CreateMapper();
CarrierLabelPrintedMessage message = new CarrierLabelPrintedMessage
{
ShipmentIdentifier = "AB1234",
Cartons = new List<Carton>
{
new Carton
{
TrackingNumber = "TestTrackingNumber",
LabelData =
new LabelData
{
Weight = 5,
WeightUnit = "none"
}
}
}
};
var command = mapper.Map<PrintLabelCommand>(message);
Assert.Equal(command.ShipmentUnits[0].Weight.Unit, WeightUnit.None);
}
public class PrintLabelCommandMappingProfile : Profile
{
public PrintLabelCommandMappingProfile()
{
CreateMap<CarrierLabelPrintedMessage, PrintLabelCommand>()
.ForMember(cmd => cmd.ShipmentId, exp => exp.MapFrom(msg => msg.ShipmentIdentifier))
.ForMember(cmd => cmd.ShipmentUnits, exp => exp.MapFrom(msg => msg.Cartons));
CreateMap<Carton, ShipmentUnit>()
.ForMember(su => su.Id, exp => exp.MapFrom(c => c.TrackingNumber))
.ForPath(su => su.Weight.Amount, exp => exp.MapFrom(c => c.LabelData.Weight))
.ForPath(su => su.Weight.Unit, exp => exp.MapFrom(c => c.LabelData.WeightUnit));
CreateMap<string, WeightUnit>().ConvertUsing((str, _) =>
{
// I want to have ShipmentIdentifier field to be accessible in the upper level to implement the mapping logic here as below
//if (ShipmentIdentifier.StartsWith("AB")) // it's "AB1234" in the sample
// return WeightUnit.None;
//else
return WeightUnit.Grams;
});
}
}
public class CarrierLabelPrintedMessage
{
public string ShipmentIdentifier { get; set; }
public List<Carton> Cartons { get; set; }
}
public class PrintLabelCommand
{
public string ShipmentId { get; set; }
public List<ShipmentUnit> ShipmentUnits { get; set; }
}
public class Carton
{
public string TrackingNumber { get; set; }
public LabelData LabelData { get; set; }
}
public class LabelData
{
public double Weight { get; set; }
public string WeightUnit { get; set; }
}
public class ShipmentUnit
{
public string Id { get; set; }
public Weight Weight { get; set; }
}
public class Weight
{
public double Amount { get; set; }
public WeightUnit Unit { get; set; }
}
public enum WeightUnit
{
None,
Grams,
Kilograms
}
}
}
有什么想法吗?
您可以在 CreateMap<CarrierLabelPrintedMessage, PrintLabelCommand>()
映射上使用 AfterMap()
,以根据 CarrierLabelPrintedMessage
中可用的信息“修复”映射。映射可能如下所示:
CreateMap<CarrierLabelPrintedMessage, PrintLabelCommand>()
.ForMember(cmd => cmd.ShipmentId, exp => exp.MapFrom(msg => msg.ShipmentIdentifier))
.ForMember(cmd => cmd.ShipmentUnits, exp => exp.MapFrom(msg => msg.Cartons))
.AfterMap((src, target) => {
WeightUnit targetValue = WeightUnit.Grams;
if (src.ShipmentIdentifier.StartsWith("AB"))
{
targetValue = WeightUnit.None;
}
foreach (ShipmentUnit shipmentUnit in target.ShipmentUnits)
{
shipmentUnit.Weight.Unit = targetValue;
}
});