2012-11-12 37 views
6

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

は、例えば、1つまたは複数のX、からの一覧を取得することです

には、以下のソースクラスを考えてみましょう:

これを達成するためにどのようなマッピング設定を使用するかわかりません。 MapFromは1:1のコンポジションを作成する方法と似ていますが、AutoMapperの保存先命名規則を使用しない限り、配列(または他の列挙型)を処理できないようです。

これを達成するための洞察はありますか?

答えて

8

は、私はしばらく前に非常によく似た問題を抱えていた

Mapper.CreateMap<Z, Destination>(); 
Mapper.CreateMap<Y, Destination>(); 
Mapper.CreateMap<X, Destination>() 
    .ForMember(destination => destination.A, options => options.MapFrom(source => source.A)).IgnoreAllNonExisting() 
    .ForMember(destination => destination.C, options => options.MapFrom(source => Mapper.Map<IEnumerable<Y>, IEnumerable<Destination>>(source.B).FirstOrDefault().C)) 
    .ForMember(destination => destination.E, options => options.MapFrom(source => Mapper.Map<IEnumerable<Z>, IEnumerable<Destination>>(source.B.SelectMany(d => d.D)).FirstOrDefault().E)) 
    .ForMember(destination => destination.F, options => options.MapFrom(source => Mapper.Map<IEnumerable<Z>, IEnumerable<Destination>>(source.B.SelectMany(d => d.D)).FirstOrDefault().F)); 

var result = Mapper.Map<IEnumerable<X>, IEnumerable<Destination>>(arrayOfX); 
+0

スローされます。ここでは

​​

は、マッピングを検証し、行動でそれを表示するユニットテストのカップルですAutoMapperMappingException - BまたはDがnullまたは長さがゼロの配列の場合 X [] arrayOfX = new X [] {新しいX(){A = "a1"、B = null}、新しいX(){A = "a2"、B =新しいY [] {}}}; –

+0

@JayWalker自分の投稿を編集しました。ちょうどヌルチェックが追加されました。見つけてくれてありがとう。 –

3

、このマッパーを試してみてください。私には場所のコレクションがあり、各場所には通りのコレクションがありました。私は、各ビューモデルが通りを表すビューモデルのコレクション(場所の詳細を含む)にそれらをマップしたかったのです。

この

は私の解決策だった: https://groups.google.com/forum/#!topic/automapper-users/b66c1M8eS8E

この特定の問題については、これはあなたのマッピング設定することができます

public static class AutoMapperConfig 
{ 
    public static void Configure() 
    { 
     Mapper.CreateMap<Z, Destination>() 
      .ForMember(dest => dest.A, opt => opt.Ignore()) 
      .ForMember(dest => dest.C, opt => opt.Ignore()); 

     Mapper.CreateMap<Y, Destination>() 
      .ForMember(dest => dest.A, opt => opt.Ignore()) 
      .ForMember(dest => dest.E, opt => opt.Ignore()) 
      .ForMember(dest => dest.F, opt => opt.Ignore()); 

     Mapper.CreateMap<X, Destination>() 
      .ForMember(dest => dest.C, opt => opt.Ignore()) 
      .ForMember(dest => dest.E, opt => opt.Ignore()) 
      .ForMember(dest => dest.F, opt => opt.Ignore()); 
    } 
} 

AutoMapperであるため、主に1:1のマッピングは、あなたがほんの少しを実装する必要があります複数のオブジェクトにマップする魔法これは、あなたのオブジェクトを移入するためにそのマッピングを呼び出すことができる方法の例です:

[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 => x.B.SelectMany(
       y => y.D 
        .Select(Mapper.Map<Z, Destination>) 
        .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 => x.F == "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")); 
    } 
} 
関連する問題