2012-06-17 8 views
6

की दीप कॉपी मैं सी # में लिखे गए कुछ कोड पर काम कर रहा हूं। इस एप्लिकेशन में, मैं एक कस्टम संकलन इस प्रकार परिभाषित किया गया है:सी # ऑब्जेक्ट

public class ResultList<T> : IEnumerable<T> 
{ 
    public List<T> Results { get; set; } 
    public decimal CenterLatitude { get; set; } 
    public decimal CenterLongitude { get; set; } 
} 

प्रकार परिणाम द्वारा इस्तेमाल किया तीन कस्टम प्रकार से एक हैं। प्रत्येक कस्टम प्रकार के गुण केवल आदिम प्रकार हैं (इनट्स, तार, बूल, int ?, बूल?)।

public class ResultItem 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public bool? isLegit { get; set; } 
} 

कैसे मैं एक ResultList उद्देश्य यह है कि मेरे द्वारा बनाए गए की एक गहरी प्रतिलिपि प्रदर्शन करते हैं: यहां कस्टम प्रकारों में से एक का एक उदाहरण है। मुझे यह पोस्ट मिला: Generic method to create deep copy of all elements in a collection। हालांकि, मैं यह नहीं समझ सकता कि इसे कैसे किया जाए।

+0

आप क्या कोशिश की है? आपको क्या त्रुटि संदेश मिला? जॉन स्कीट का कोड जो आपने पाया वह बस काम करता है जहां तक ​​मैं देख सकता हूं। –

+0

शालो या गहरी प्रतिलिपि? http://stackoverflow.com/questions/11073196/shallow-copy-of-a-custom-c-sharp-object –

+0

आप [इस queston] के ओपी और ओपी क्यों हैं (http://stackoverflow.com/questions/ 11073196/उथ-प्रति-एक-कस्टम-सी-तीक्ष-वस्तु) आपके उदाहरण में सटीक उसी डेटा संरचना का उपयोग करने लग रहा है? –

उत्तर

8

कारण हैं कि आपके ResultList वर्ग के साथ काम नहीं करेगा में से एक जॉन स्कीट का example ऐसा इसलिए है क्योंकि यह आईसीएलनेबल इंटरफ़ेस को लागू नहीं करता है।

क्लोन की आवश्यकता वाले सभी वर्गों पर आईसीएलनेबल लागू करें, उदा।

public class ResultItem : ICloneable 
{ 
    public object Clone() 
    { 
    var item = new ResultItem 
       { 
        ID = ID, 
        Name = Name, 
        isLegit = isLegit 
       }; 
    return item; 
    } 
} 

और यह भी ResultList पर:

public class ResultList<T> : IEnumerable<T>, ICloneable where T : ICloneable 
{ 
    public List<T> Results { get; set; } 
    public decimal CenterLatitude { get; set; } 
    public decimal CenterLongitude { get; set; } 

    public object Clone() 
    { 
    var list = new ResultList<T> 
       { 
        CenterLatitude = CenterLatitude, 
        CenterLongitude = CenterLongitude, 
        Results = Results.Select(x => x.Clone()).Cast<T>().ToList() 
       }; 
    return list; 
    } 
} 

फिर अपने वस्तु की एक गहरी प्रतिलिपि बनाने के लिए:

resultList.clone(); 
+0

ग्रेट स्पष्टीकरण। आपकी मदद के लिए बहुत बहुत धन्यवाद। – user70192

12

कम से कम कोडिंग प्रयास शामिल दृष्टिकोण BinaryFormatter के माध्यम से धारावाहिक और deserializing है।

आप निम्न विस्तार विधि (Kilhoffer’s answer से लिया गया) निर्धारित कर सकते हैं:

public static T DeepClone<T>(T obj) 
{ 
    using (var ms = new MemoryStream()) 
    { 
     var formatter = new BinaryFormatter(); 
     formatter.Serialize(ms, obj); 
     ms.Position = 0; 
     return (T)formatter.Deserialize(ms); 
    } 
} 

... और फिर बस फोन:

ResultList<T> clone = DeepClone(original); 
1

यहाँ, कुछ है कि मैं जरूरत है और लिखा है इसे कॉपी प्रतिबिंब का उपयोग करता है प्रत्येक संपत्ति (और निर्दिष्ट अगर निजी)

public static class ObjectCloner 
{ 
    public static T Clone<T>(object obj, bool deep = false) where T : new() 
    { 
     if (!(obj is T)) 
     { 
      throw new Exception("Cloning object must match output type"); 
     } 

     return (T)Clone(obj, deep); 
    } 

    public static object Clone(object obj, bool deep) 
    { 
     if (obj == null) 
     { 
      return null; 
     } 

     Type objType = obj.GetType(); 

     if (objType.IsPrimitive || objType == typeof(string) || objType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == 0) == null) 
     { 
      return obj; 
     } 

     List<PropertyInfo> properties = objType.GetProperties().ToList(); 
     if (deep) 
     { 
      properties.AddRange(objType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)); 
     } 

     object newObj = Activator.CreateInstance(objType); 

     foreach (var prop in properties) 
     { 
      if (prop.GetSetMethod() != null) 
      { 
       object propValue = prop.GetValue(obj, null); 
       object clone = Clone(propValue, deep); 
       prop.SetValue(newObj, clone, null); 
      } 
     } 

     return newObj; 
    } 
} 
+0

सूची प्राप्त करने वाली ऑब्जेक्ट्स को संभालें: टिप्पणियों में कोड चूसने के बाद से मैं दूसरा जवाब दूंगा। – jeromeyers

3

@ जॉर्जी-यह, मैं गुण जिसका प्रकार संभाल करने के लिए अपने कोड को संशोधित करने की थी पर विस्तार सूची विरासत:

public static class ObjectCloner { 
    public static T Clone<T>(object obj, bool deep = false) where T : new() { 
     if (!(obj is T)) { 
      throw new Exception("Cloning object must match output type"); 
     } 

     return (T)Clone(obj, deep); 
    } 

    public static object Clone(object obj, bool deep) { 
     if (obj == null) { 
      return null; 
     } 

     Type objType = obj.GetType(); 

     if (objType.IsPrimitive || objType == typeof(string) || objType.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == 0) == null) { 
      return obj; 
     } 

     List<PropertyInfo> properties = objType.GetProperties().ToList(); 
     if (deep) { 
      properties.AddRange(objType.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic)); 
     } 

     object newObj = Activator.CreateInstance(objType); 

     foreach (var prop in properties) { 
      if (prop.GetSetMethod() != null) { 
       var proceed = true; 
       if (obj is IList) { 
        var listType = obj.GetType().GetProperty("Item").PropertyType; 
        if (prop.PropertyType == listType) { 
         proceed = false; 
         foreach (var item in obj as IList) { 
          object clone = Clone(item, deep); 
          (newObj as IList).Add(clone);        
         }       
        }      
       } 

       if (proceed) { 
        object propValue = prop.GetValue(obj, null); 
        object clone = Clone(propValue, deep); 
        prop.SetValue(newObj, clone, null); 
       }     
      } 
     } 

     return newObj; 
    } 
} 
संबंधित मुद्दे