AutoMapper和展平嵌套数组
我正在尝试使用AutoMapper来压缩多个级别的数组。
考虑以下源类:
class X { public string A { get; set; } public Y[] B { get; set; } } class Y { public string C { get; set; } public Z[] D { get; set; } } class Z { public string E { get; set; } public string F { get; set; } }
以下目的地:
class Destination { public string A { get; set; } public string C { get; set; } public string E { get; set; } public string F { get; set; } }
我希望能够做的是从一个或多个X获取一个List,例如:
Mapper.Map<IEnumerable, IEnumerable>(arrayOfX);
我无法弄清楚用什么类型的映射配置来实现这一目标。 MapFrom似乎是1:1合成的方式,但似乎无法处理数组(或其他可枚举),除非我使用AutoMapper的目标命名约定。
有关如何实现这一目标的任何见解?
试试这个映射器,
Mapper.CreateMap(); Mapper.CreateMap(); Mapper.CreateMap() .ForMember(destination => destination.A, options => options.MapFrom(source => source.A)).IgnoreAllNonExisting() .ForMember(destination => destination.C, options => options.MapFrom(source => Mapper.Map, IEnumerable>(source.B).FirstOrDefault().C)) .ForMember(destination => destination.E, options => options.MapFrom(source => Mapper.Map, IEnumerable>(source.B.SelectMany(d => dD)).FirstOrDefault().E)) .ForMember(destination => destination.F, options => options.MapFrom(source => Mapper.Map, IEnumerable>(source.B.SelectMany(d => dD)).FirstOrDefault().F)); var result = Mapper.Map, IEnumerable>(arrayOfX);
我刚才有一个非常类似的问题。 我收集了一些地点,每个地点都有一系列街道。 我想将它们映射到一组视图模型,其中每个视图模型代表一条街道(包括位置详细信息)。
这是我的解决方案: https : //groups.google.com/forum/#!topic /automapper-users / b66c1M8eS8E
对于这个特殊问题,这可能是您的映射配置:
public static class AutoMapperConfig { public static void Configure() { Mapper.CreateMap() .ForMember(dest => dest.A, opt => opt.Ignore()) .ForMember(dest => dest.C, opt => opt.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.A, opt => opt.Ignore()) .ForMember(dest => dest.E, opt => opt.Ignore()) .ForMember(dest => dest.F, opt => opt.Ignore()); Mapper.CreateMap() .ForMember(dest => dest.C, opt => opt.Ignore()) .ForMember(dest => dest.E, opt => opt.Ignore()) .ForMember(dest => dest.F, opt => opt.Ignore()); } }
由于AutoMapper主要是1:1映射,因此您需要实现一点魔法来映射到多个对象。 这是一个如何调用该映射来填充对象的示例:
var rc = data.SelectMany( x => xBSelectMany( y => yD .Select(Mapper.Map) .Select(z => Mapper.Map(y, z)) ) .Select(y => Mapper.Map(x, y)) );
以下是一些unit testing,用于validation映射并将其显示在行动中:
[TestFixture] public class MapperTests { [Test] public void Mapping_Configuration_IsValid() { AutoMapperConfig.Configure(); Mapper.AssertConfigurationIsValid(); } [Test] public void Mapping_TestItems_MappedOK() { AutoMapperConfig.Configure(); Mapper.AssertConfigurationIsValid(); var data = new[] { new X { A = "A1", B = new[] { new Y { C = "A1C1", D = new[] { new Z { E = "A1C1E1", F = "A1C1F1" }, new Z { E = "A1C1E2", F = "A1C1F2" }, } }, new Y { C = "A1C2", D = new[] { new Z { E = "A1C2E1", F = "A1C2F1" }, new Z { E = "A1C2E2", F = "A1C2F2" }, } } } } }; var rc = data.SelectMany( x => xBSelectMany( y => yD .Select(Mapper.Map) .Select(z => Mapper.Map(y, z)) ) .Select(y => Mapper.Map(x, y)) ); Assert.That(rc, Is.Not.Null); Assert.That(rc.Count(), Is.EqualTo(4)); var item = rc.FirstOrDefault(x => xF == "A1C2F2"); Assert.That(item, Is.Not.Null); Assert.That(item.A, Is.EqualTo("A1")); Assert.That(item.C, Is.EqualTo("A1C2")); Assert.That(item.E, Is.EqualTo("A1C2E2")); Assert.That(item.F, Is.EqualTo("A1C2F2")); } }