2012-12-23 45 views
7

का समर्थन नहीं करता है सबसे पहले हम सभी सहमत हैं कि कस्टम ऑब्जेक्ट/इकाई के अंदर कॉपी फ़ंक्शन को लागू करने का सबसे अच्छा तरीका होगा। लेकिन इस परिदृश्य पर विचार करें। हमारे पास यह विकल्प नहीं है और हम विशिष्ट फ़ंक्शन लिखना नहीं चाहते हैं जो इकाई की सटीक प्रतिलिपि बनायेगा क्योंकि भविष्य में इकाई बदली जाएगी ताकि हमारी कॉपी फ़ंक्शन विफल हो जाए।गतिशील ऑब्जेक्ट की प्रतिलिपि बनाने का सबसे तेज़ तरीका है जो कॉपी फ़ंक्शन

[Serializable] 
class MyEntity 
{ 
    public MyEntity() 
    { 
    } 

    public MyEntity(int id, string name) 
    { 
     this.Id = id; 
     this.Name = name; 
    } 

    public int Id { get; set; } 

    public string Name { get; set; } 

    public MyEntity Copy() 
    { 
     throw new NotImplementedException(); 
    } 
} 

सभी आवश्यकताओं को कवर करने के लिए ऊपर मैं दो समाधान के साथ आया था:

 //original... 
     MyEntity original = new MyEntity() { Id = 1, Name = "demo1" }; 

     //first way to copy object... 
     List<MyEntity> list = new List<MyEntity>() { original}; 
     MyEntity copy1 = list.ConvertAll(entity => new MyEntity(entity.Id, entity.Name))[0]; 

     //second way to copy object... 
     byte[] bytes = SerializeEntity(original); 
     MyEntity copy2 = (MyEntity)DeserializeData(bytes); 


    byte[] SerializeEntity(object data) 
    { 
     byte[] result = null; 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      BinaryFormatter formatter = new BinaryFormatter(); 
      formatter.Serialize(ms, data); 
      result = ms.ToArray(); 
     } 
     return result; 
    } 

    object DeserializeData(byte[] data) 
    { 
     object result = null; 
     using(MemoryStream ms = new MemoryStream(data)) 
     { 
      BinaryFormatter formatter = new BinaryFormatter(); 
      result = formatter.Deserialize(ms); 
     } 
     return result; 
    } 

और अब सवाल

यहाँ वर्तमान इकाई के संस्करण सरलीकृत है। दृश्य के पीछे सबसे इष्टतम समाधान क्या है और क्यों, पहला या दूसरा? क्या ऊपर की आवश्यकताओं पर विचार करने के लिए सटीक प्रतिलिपि करने का कोई बेहतर तरीका है? बड़ी संख्या में प्रतियां की जाएगी।

पीएस नोट: मुझे पता है कि पहला तरीका मूल रूप से पहले से ही एक कॉपी फ़ंक्शन है क्योंकि होन्ज़ा ने बताया। मैं serialization के रूप में बहुमुखी और कस्टम कॉपी समारोह के रूप में तेजी से कुछ दिख रहा हूँ।

उत्तर

1

आप AutoMapper उपयोग करने के लिए कोशिश कर सकते:

Mapper.CreateMap<MyEntity, MyEntity>(); 

... 

var copy3 = Mapper.Map<MyEntity, MyEntity>(original); 
+0

मैंने ऑटोमैपर के बारे में कुछ पोस्ट पढ़ी थीं लेकिन मेरे प्रदर्शन के बारे में कोई वास्तविक निष्कर्ष नहीं बना सका, मैं अपने मामले में उम्मीद कर सकता हूं। कुछ लोग दावा करते हैं कि सभी मामलों के लिए सबसे अच्छा समाधान नहीं है। क्या आप किसी भी पॉइंटर्स का सुझाव दे सकते हैं जिसके परिणामस्वरूप ऑटोमैपर का उपयोग करके खराब प्रदर्शन हो सकता है? इस पल में वैकल्पिक के लिए +1 –

7

सबसे पहले हम सभी सहमत हैं कि कस्टम ऑब्जेक्ट/इकाई के अंदर कॉपी फ़ंक्शन को लागू करने का सबसे अच्छा तरीका होगा।

मैं सहमत नहीं हूं। मुझे हर बार ऐसी विधियों को लिखने से नफरत है। एक विस्तार विधि का उपयोग करके मेरा सुझाव यहां दिया गया है:

public static T Copy<T>(this T obj) 
    where T : class 
{ 
    using (MemoryStream stream = new MemoryStream()) 
    { 
     BinaryFormatter formatter = new BinaryFormatter(); 
     formatter.Serialize(stream, obj); 

     stream.Seek(0, SeekOrigin.Begin); 
     return formatter.Deserialize(stream) as T; 
    } 
} 

यह मूल रूप से आपका दूसरा समाधान है लेकिन थोड़ा अनुकूलित है। मेमोरीस्ट्रीम को बाइट सरणी में कॉपी करने की आवश्यकता नहीं है और उसके बाद से एक और मेमोरीस्ट्रीम बनाएं।

सबसे अच्छी बात यह है कि यह सामान्य है जिसका उपयोग प्रत्येक ऑब्जेक्ट के साथ किया जा सकता है जिसमें [Serializable] विशेषता है। और मुझे पूरा यकीन है कि यह आपके पहले समाधान से तेज़ है जहां आपको प्रत्येक संपत्ति का उपयोग करना होगा (हालांकि मुझे माप नहीं आया)।

संपादित करें:

ठीक है, मैं वास्तव में अब कुछ मापने किया था। प्रदर्शन के लिए मेरी पहली धारणा पूरी तरह गलत थी!

मैं यादृच्छिक मूल्यों के साथ 1000000 MyEntity ऑब्जेक्ट का निर्माण होगा और फिर उन्हें कॉपी किया (मैं भी Honza Brestan के गहरे और उथले प्रतियों पर संकेत माना जाता है):

द्विआधारी formatter के साथ गहरे प्रतिलिपि: 14.727 रों
कॉपी विधि के साथ गहरी प्रतिलिपि : 0.490 रों
प्रतिबिंब के साथ उथले प्रतिलिपि: 5.499 रों
कॉपी विधि के साथ उथले प्रतिलिपि: 0.144 रों

+0

यह, कुछ हम उपयोग करने के लिए इसी तरह की है, तथापि, यह ध्यान देने योग्य है कि हर बार एक अलग 'टी' आपूर्ति की है एक नई पद्धति होना होगा हो सकता है संकलक द्वारा उत्पन्न किया गया। इससे थोड़ा सी CPU ओवरहेड और अधिक मेमोरी का उपयोग किया जाएगा। – MadSkunk

+0

सीरियलाइजेशन का उपयोग करके @pescolino वास्तव में सबसे बुलेट प्रूफ है यदि ऑब्जेक्ट को धारावाहिक के रूप में चिह्नित किया गया है, लेकिन यह भी सबसे धीमा है। मैं वास्तव में एक प्रतिलिपि करने के लिए कुछ स्मार्ट और तेज़ तरीका पाने के लिए तैयार हूं, हालांकि मुझे पता है कि कोई "मुफ्त लंच" नहीं है। आप हमेशा दूसरी चीज हासिल करने के लिए कुछ खो देते हैं। –

+0

@ ग्रेगोर प्राइमर पढ़ें [प्रदर्शन प्रतिबिंब में सुधार, मुझे किन विकल्पों पर विचार करना चाहिए] (http://stackoverflow.com/questions/1027980/improving-performance-reflection-what-alternatives-should-i-consider) और विशेष रूप से [जॉन स्कीट का ब्लॉग ] (http://msmvps.com/blogs/jon_skeet/archive/2008/08/09/making-reflection-fly-and-exploring-delegates.aspx) जैसा कि उनके उत्तर में बताया गया है। – pescolino

1

अपने पहले ही प्रयास और अपने खुद के कॉपी विधि लेखन के बीच क्या अंतर है?

public MyEntity Copy() 
{ 
    return new MyEntity(this.Id, this.Name); 
} 

मेरे लिए यह अपने संग्रह का प्रयास है, जो वास्तव में वैसे भी एक ही होता है की तुलना में बेहतर लग रहा है - दोनों ही मामलों में आप स्पष्ट रूप से सभी गुण नाम के लिए है।

आप इकाई वर्ग ही संशोधित नहीं कर सकते हैं, तो आप अभी भी एक विस्तार विधि

public static MyEntity Copy(this MyEntity source) 
{ 
    return new MyEntity(source.Id, source.Name); 
} 

दूसरा प्रयास के रूप में (एक स्थिर वर्ग जहां प्रति तर्क का उपयोग करना चाहते से दिखाई में रखा), बना सकते हैं क्या आपने दोनों के बीच अंतर माना है? वे काफी समान नहीं हैं। सबसे पहले उथले प्रतिलिपि बनाता है, जबकि दूसरा (पूरे ऑब्जेक्ट पेड़ को क्रमबद्ध करने योग्य है) गहरी प्रतिलिपि बनाता है। अंतर यह है कि इसकी गुणों की प्रतिलिपि बनाई गई है या मूल वस्तु दोनों और इसकी प्रतिलिपि एक ही वस्तु का संदर्भ देती है। यह पेस्कोलोनो के संस्करण पर भी लागू होता है, जो बहुत अच्छा बीटीडब्ल्यू दिखता है।

तो सवाल यह है कि आप कौन सी प्रतिलिपि चाहते हैं/आवश्यकता है।

वास्तव में एक गतिशील (अभी तक शायद काफी प्रभावी नहीं) उथले प्रतिलिपि विधि के लिए मुझे लगता है कि आप प्रतिबिंब का उपयोग करने, सभी गुण की गणना और कॉपी करने के लिए मूल वस्तु से उनके मूल्यों को कॉपी की आवश्यकता होगी। गैर-पूरा डेमो संस्करण इस प्रकार दिखाई देंगे:

public static MyEntity Copy(this MyEntity source) 
{ 
    var result = new MyEntity(); 

    var properties = source.GetType().GetProperties(
      BindingFlags.Instance | BindingFlags.Public); 

    foreach (var property in properties) 
    { 
     var val = property.GetValue(source, null); 
     property.SetValue(result, val, null); 
    } 

    return result; 
} 

यह दृष्टिकोण अपने आप ही, अर्थात् प्रदर्शन, विशेष मामलों (indexers, गैर सरकारी संपत्तियों ...) को संभालने के लिए समय-समय पर जरूरत के लिए समस्या है, लेकिन मिल जाएगा काम किया और unserializable वस्तुओं पर भी काम करता है। जेनेरिक संस्करण भी करना आसान होगा - यह आपके ऊपर है, चाहे आपको इसकी आवश्यकता हो।

ध्यान देने योग्य भी है क्योंकि मुझे और पेस्कोलोनो दोनों विस्तार विधियों का उपयोग करने का प्रस्ताव देते हैं, उनके साथ एक संभावित समस्या है। यदि आपकी इकाई में वास्तव में एक्सटेंशन के समान हस्ताक्षर के साथ Copy विधि है, तो संकलक एक्सटेंशन के बजाय इसका उपयोग करने का निर्णय लेगा। बुलाए जाने पर यह स्पष्ट रूप से NotImplementedException फेंक देगा। तो अगर यह मामला है (और यह सिर्फ आपका नमूना कोड नहीं है), तो यह गंभीर "गॉचा" हो सकता था। इस तरह के मामले में एकमात्र समाधान एक्सटेंशन विधि के हस्ताक्षर को बदलना है, अधिमानतः अपना नाम बदलकर।

+0

मैं आपसे सहमत हूं कि यह एक बड़ा अंतर नहीं है। एकमात्र "उज्ज्वल" बिंदु यह है कि अगर निर्माता बदल जाता है तो मुझे अपवाद मिलेगा। पहली जगह में मैं सबसे तेज़ संभव विकल्प लिखना चाहता था, नया उदाहरण बना सकता हूं और व्यक्तिगत गुण सेट कर सकता हूं। हालांकि इस दृष्टिकोण में अगर नई संपत्ति पेश की जाती है तो मुझे अपवाद नहीं मिलेगा। मूल रूप से इसके बारे में जानने के बिना अवैध प्रतिलिपि बनाना। पाठ्यक्रम का आपका नमूना इस मुद्दे को शामिल करता है। –