2012-11-12 14 views
6

मैं ऐरे के कई स्तरों को फ़्लैट करने के लिए ऑटोमैपर का उपयोग करने की कोशिश कर रहा हूं।ऑटोमैपर और नेस्टेड सरणी flattening

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

मैं ऐसा करने में सक्षम होने के लिए क्या करना चाहते हैं एक या अधिक एक्स, जैसे से एक सूची प्राप्त है

निम्नलिखित स्रोत वर्गों पर विचार करें :

Mapper.Map<IEnumerable<X>, IEnumerable<Destination>>(arrayOfX); 

मैं यह समझने में असमर्थ हूं कि यह प्राप्त करने के लिए किस प्रकार की मैपिंग कॉन्फ़िगरेशन का उपयोग करना है। MapFrom 1: 1 रचनाओं के लिए जाने का तरीका प्रतीत होता है, लेकिन ऐसा लगता है कि जब तक मैं ऑटोमैपर के गंतव्य नामकरण सम्मेलन का उपयोग नहीं करता तब तक सरणी (या अन्य गणनीय) को संभालने में सक्षम नहीं लगता है।

इसे प्राप्त करने के तरीके पर कोई अंतर्दृष्टि?

उत्तर

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

यह एक फेंक देगा:

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

यहाँ मानचित्रण को मान्य और कार्रवाई में यह दिखाने के लिए इकाई परीक्षण के एक जोड़े हैं: इस तरह आप अपने वस्तु को भरने के लिए है कि मानचित्रण कह सकते हैं का एक उदाहरण है ऑटोमैपर मैपिंग अपवाद अगर बी या डी शून्य या शून्य-लंबाई सरणी है। एक्स [] arrayOfX = नया एक्स [] {नया एक्स() {ए = "ए 1", बी = नल}, नया एक्स() {ए = "ए 2", बी = नया वाई [] {}}}; –

+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")); 
    } 
} 
संबंधित मुद्दे