2012-07-04 12 views
22

जब ऑटोमैपर किसी ऑब्जेक्ट से मुकाबला करता है जिसे पहले ही मैप किया गया है, ऐसा लगता है कि इसे फिर से मैप करने की कोशिश करने के बजाय उस ऑब्जेक्ट का फिर से उपयोग करना प्रतीत होता है। मेरा मानना ​​है कि यह .Equals() पर आधारित है।मैप किए गए ऑब्जेक्ट कैश न करने के लिए मैं ऑटोमैपर कैसे प्राप्त करूं?

मेरे पास एक पेड़ है जिसे मैप किया जा रहा है। तो, कुछ गुणों और बच्चों के साथ एक नोड। नोड्स में से एक से अधिक .Equals() का वैल्यू है, क्योंकि यह एक आईडी प्रॉपर्टी पर आधारित है। नोड्स के बच्चे अलग हैं और मुझे उन दोबारा मैप की जरूरत है, लेकिन यह एक कैश किए गए मानचित्र मान का उपयोग कर रहा है।

कैश मैपिंग बंद करने का कोई तरीका है? मैं सोच सकता हूं कि एक नया कनवर्टर लागू कर रहा है, लेकिन यह ऑटोमैपर का उपयोग करने के उद्देश्य को पूरी तरह से हरा देता है।

यहां पुन: पेश करने के तरीके पर एक उदाहरण दिया गया है।

void Main() 
{ 
    var source = new List<Tag> 
    { 
     new Tag 
     { 
      Id = 1, 
      Name = "Tag 1", 
      ChildTags = new List<Tag> 
      { 
       new Tag 
       { 
        Id = 2, 
        Name = "Tag 2", 
        ChildTags = new List<Tag> 
        { 
         new Tag {Id = 3, Name = "Tag 3"}, 
         new Tag {Id = 4, Name = "Tag 4"} 
        } 
       } 
      } 
     }, 
     new Tag { Id = 1, Name = "Tag 1" }, 
     new Tag 
     { 
      Id = 3, Name = "Tag 3", ChildTags = new List<Tag> 
      { 
       new Tag {Id = 4, Name = "Tag 4"} 
      } 
     } 
    }; 

    Mapper.CreateMap<Tag, Tag>(); 
    var results = Mapper.Map<IList<Tag>, IList<Tag>>(source); 

    results.Dump(); 
} 

public class Tag 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public IEnumerable<Tag> ChildTags { get; set; } 

    public override bool Equals(Object obj) 
    { 
     if (obj == null) 
     { 
      return false; 
     } 

     var x = this; 
     var y = (Tag)obj; 

     return x.Id.Equals(y.Id); 
    } 

    public override int GetHashCode() 
    { 
     return Id.GetHashCode(); 
    } 
} 
+0

इस बारे में मिली केवल एक संदर्भ: https://groups.google.com/forum/?fromgroups#!topic/automapper-users/8ThkaCk_3fc। –

+0

मैं मैपिंगइंजिन को तुरंत चालू करने और जीवन चक्र को नियंत्रित करने की कोशिश करता हूं जैसे कि कहता है और देखता है कि वह वह चाल करेगा या नहीं। –

+0

तो, ऐसा लगता है कि मुझे एक ITypeMapFactory को लागू करने की आवश्यकता होगी। मुझे जो करना है उसके लिए यह बहुत अधिक काम है। अगर इसे बंद करने का कोई आसान तरीका था, तो यह अच्छा होगा, लेकिन ऐसा नहीं लगता है। यदि आप इस प्रश्न का उत्तर बनाना चाहते हैं और इसमें एक उदाहरण देना चाहते हैं, तो मैं इसे आपके लिए उत्तर के रूप में चिह्नित करूंगा। –

उत्तर

9

अब कैश निष्क्रिय करने के लिए एक विकल्प है।

Mapper.CreateMap<Tag, Tag>(); 
var results = Mapper.Map<IList<Tag>, IList<Tag>>(source, opt => opt.DisableCache = true); 
1

जब AutoMapper एक वस्तु है कि पहले से ही मैप किया गया सामना करना पड़ता है, यह , फिर से उस वस्तु का उपयोग करने के बजाय-नक्शा फिर से यह कोशिश कर के लगता है। I मानते हैं कि यह इस पर आधारित है।()

क्या आप समझा सकते हैं कि आप कब और कब देखते हैं?

स्रोत कोड में त्वरित रूप से देखने के बाद, मुझे यकीन है कि वस्तुओं के लिए कोई कैश नहीं है।

public class CustomerSource 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
     public DateTime DateOfBirth { get; set; } 

     public int NumberOfOrders { get; set; } 
    } 

    public class CustomerTarget 
    { 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
     public DateTime DateOfBirth { get; set; } 

     public int NumberOfOrders { get; set; } 
    } 

    [TestMethod] 
    public void Test_AutoMapper() 
    { 
     Mapper.CreateMap<CustomerSource, CustomerTarget>(); 

     var source = new CustomerSource() { DateOfBirth = DateTime.Now, FirstName = "FirstName", LastName = "LastName", NumberOfOrders = int.MaxValue }; 

     var res1 = Mapper.Map<CustomerSource, CustomerTarget>(source); 
     Console.WriteLine(res1.FirstName); // PRINT FirstName 

     source.FirstName += "[UPDATED]"; 
     source.LastName += "[UPDATED]"; 

     var res2 = Mapper.Map<CustomerSource, CustomerTarget>(source); 
     Console.WriteLine(res1.FirstName); // PRINT FirstName[UPDATED] 

    } 
अपने कोड के बिना

, यह और अधिक गहराई से जाने के लिए मुश्किल है: यहाँ एक परीक्षण है कि इस उदाहरण देकर स्पष्ट करना है। एक विधि मैपर.रसेट() है जो मैपरइंजिन और मैपिंग कॉन्फ़िगरेशन को साफ़ करता है (सभी आंतरिक मैपिंग एक्सप्रेशन खो जाएंगे)

+0

सायन के "उत्तर" में कोड है। –

+0

तो, उसका जवाब – Cybermaxs

+0

क्षमा करें, मैं कह रहा था कि उसके उत्तर में कोड का पुनरुत्पादन दिखा रहा है। मैंने उद्धरणों में "उत्तर" कहा क्योंकि यह कोई जवाब नहीं था, लेकिन एक टिप्पणी थी। –

4

मुझे भी यही समस्या मिलती है। ऐसा तब नहीं होता जब आप एक ही ऑब्जेक्ट को दो बार मैप करते हैं - ऐसा तब होता है जब आपके पास ऑब्जेक्ट्स का पेड़ वाररासी होता है, और पेड़ के दो स्थानों (लेकिन विभिन्न बाल मूल्यों के साथ) में वही मान मौजूद होता है दूसरे उदाहरण का मानचित्रण करते समय आइटम - यह बच्चे के मूल्यों का पुनर्मूल्यांकन करने के बजाय, पहले उदाहरण के बाल मूल्यों का उपयोग करता है।

यहाँ मेरी उदाहरण है:

class Tag { 
    int Id {get; set;} 
    string Name {get; set;} 
    IEnumerable<Tag> ChildTags {get; set;} 
} 

public void Test() 
{ 
var source = new List<Tag> 
      { 
       new Tag { Id = 1, Name = "Tag 1", ChildTags = new List<Tag> 
          { 
           new Tag { Id = 2, Name = "Tag 2", ChildTags = new List<Tag> 
              { 
               new Tag {Id = 3, Name = "Tag 3"}, 
               new Tag {Id = 4, Name = "Tag 4"} 
              } 
            } 
          } 
        }, 
       new Tag { Id = 1, Name = "Tag 1" }, 
       new Tag { 
         Id = 3, Name = "Tag 3", ChildTags = new List<Tag> 
          { 
           new Tag {Id = 4, Name = "Tag 4"} 
          } 
        } 
      }; 

Mapper.CreateMap<Tag, Tag>() 
    .ForMember(dest => dest.ChildTags, 
     opt => opt.MapFrom(src => src.ChildTags)); 
var result = Mapper.Map<IList<Tag>, IList<Tag>>(tags); 
} 

परिणाम में

  • टैग 1 का पहला उदाहरण (यानी स्रोत [0]) और उसके बच्चों के सभी परिपूर्ण हैं

  • टैग 1 (यानी स्रोत [1]) का दूसरा उदाहरण पहले उदाहरण के सभी बच्चे हैं - इसमें कोई बच्चा नहीं होना चाहिए

  • टैग 3 के दूसरे उदाहरण (यानी स्रोत [2]) किसी भी बच्चों को नहीं है - यह एक बच्चे के रूप में टैग 4 होना चाहिए

+0

संदर्भ के लिए: https://github.com/AutoMapper/AutoMapper/issues/256 –

0

ऐसा लगता है कि पेड़ वस्तु आप कर रहे हैं के व्यवहार के बराबर है मैपिंग अनुचित है।

विधि केवल तभी सत्य होनी चाहिए जब "निर्दिष्ट ऑब्जेक्ट वर्तमान ऑब्जेक्ट के बराबर है।" - http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx

आपके मामले में, आप दो पेड़ वस्तुओं एक ही आईडी साझा करने है, लेकिन स्पष्ट रूप से, वे नहीं कर रहे हैं" बराबर "के बाद से वे अलग अलग बच्चे हैं

मैं क्यों बराबर तरीका है पर सुझाव देते हैं। इस तरह से दुर्व्यवहार किया गया है और क्या आप बराबर विधि को ओवरराइड नहीं कर सकते हैं, इसके बजाय पेड़ आईडी फ़ील्ड को अधिक उपयुक्त नाम के साथ पेड़ आईडी फ़ील्ड को देखने के लिए एक अलग विधि का उपयोग कर सकते हैं। TreeIdsAreEqual

+1

कोई ऑब्जेक्ट बराबर बनाता है? डेटाबेस में, यह प्राथमिक कुंजी है। इसका मतलब है कि अन्य सभी फ़ील्ड अलग-अलग हो सकते हैं, भले ही हम जानते हैं कि यह एक ही चीज़ का प्रतिनिधित्व कर रहा है। –

8

मुझे इसका सामना करना पड़ा मैपर के साथ समस्या, चारों ओर देखकर मैंने पाया कि इसके लिए एक समाधान

जोड़कर
Mapper.Reset(); 

Source blog

+0

धन्यवाद, मुझे पागल कर रहा है! – Wilky

+0

हालांकि यह पेड़ परिदृश्य में काम नहीं करता है। यदि आप सायन के उदाहरण को देखते हैं और 'गेटहाशकोड' ओवरराइड करते हैं, तो आप इसे देख सकते हैं। मुझे यकीन नहीं है कि आप वहां 'Mapper.Reset() 'इंजेक्ट कर सकते हैं। –

+0

रीसेट कॉल के पहले और बाद में किया जाना चाहिए। – oqx

संबंधित मुद्दे