`
wyf
  • 浏览: 433510 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

深度Clone 一个快速,肮脏的方法(Deep Clone of a business object: the quick and dirty way)

阅读更多

原文出处:http://www.primordialcode.com/index.php/2008/10/18/deep-clone-business-object-quick-dirty/

I was implementing the IEditableObject interface for some entity classes in my current project and I needed a quick and dirty way to do the deep clone of an object, since my entity classes are shared between WCF, WPF and Silverlight (yes I’m one of the guys so crazy to build multi-target applications) I needed a method that could work in all the environments.

In WPF and WCF you can rely on the binary formatter and the serialization (entity classes have to be marked with the Serializable attribute), and use code like this:

   1: public static partial class Helpers
   2: {
   3:     public static T DeepClone<T>(this T obj)
   4:     {
   5:         T cloned = default(T);
   6:         var serializer = new BinaryFormatter();
   7:         using (var ms = new MemoryStream())
   8:         {
   9:             serializer.Serialize(ms, obj);
  10:             ms.Position = 0;
  11:             cloned = (T)serializer.Deserialize(ms);
  12:         }
  13:         return cloned;
  14:     }
  15: }

 

In Silverlight you can write something similar and use the DataContractSerializer and the xml serialization:

 1: public static partial class Helpers
   2: {
   3:     public static T DeepClone<T>(this T obj)
   4:     {
   5:         T cloned = default(T);
   6:         var serializer = new DataContractSerializer(typeof(T));
   7:         using (var ms = new MemoryStream())
   8:         {
   9:             serializer.WriteObject(ms, obj);
  10:             ms.Position = 0;
  11:             cloned = (T)serializer.ReadObject(ms);
  12:         }
  13:         return cloned;        
  14:     }
  15: }

 

Due to the restriction of Silverlight the DataContractSerializer has some limitations and they depends if you are using or not the DataContract + DataMember attributes:
With no attributes you can only serialize types that have a default public constructor with no arguments and all public fields/properties, for example something like:

1: public class TestEntityNoAttributes
   2: {
   3:     public string PublicField;
   4:  
   5:     public TestEntityNoAttributes()
   6:     {
   7:     }
   8:  
   9:     public TestEntityNoAttributes(string pub)
  10:     {
  11:         PublicField = pub;
  12:     }
  13: }

 

Using DataContract + DataMember attribute you can choose what to serialize, you do not need the default constructor anymore, but still you are limited to public fields only...unless you use the InternalsVisibleTo attribute and convert the protected and private fields you want to serialize to internal, the class will look like:

1: [DataContract]
   2: public class TestEntityAttributes
   3: {
   4:     [DataMember]
   5:     public string PublicField;
   6:  
   7:     /// <summary>
   8:     /// changed from protected to internal
   9:     /// it has to be internal to allow serialization and be used with InternalsVisibleTo assembly attribute
  10:     /// </summary>
  11:     [DataMember]
  12:     internal string _ProtectedField;
  13:     public string ProtectedField
  14:     {
  15:         get { return _ProtectedField; }
  16:     }
  17:  
  18:     /// <summary>
  19:     /// changed from private to internal
  20:     /// it has to be internal to allow serialization and be used with InternalsVisibleTo assembly attribute
  21:     /// </summary>
  22:     [DataMember]
  23:     internal string _PrivateField;
  24:     public string PrivateField
  25:     {
  26:         get { return _PrivateField; }
  27:     }
  28:  
  29:     public TestEntityAttributes(string pub, string pro, string pri)
  30:     {
  31:         PublicField = pub;
  32:         _ProtectedField = pro;
  33:         _PrivateField = pri;
  34:     }
  35: }

 

plus you have to tag the assembly that holds the entities and make its internal members visibile to the serializer, since DataContractSerializer resides in the System.Runtime.Serialization you have to mark the assembly with:

 1: //needed to allow the serializer to access internal members
   2: [assembly: InternalsVisibleTo("System.Runtime.Serialization")]

 

Then using the Silverlight Unit Testing Framework from Jeff Wilcox, you can write a couple of tests like the following ones to verify that it works.

1: [TestMethod]
   2: public void TestEntityNoAttributeDeepClone()
   3: {
   4:     TestEntityNoAttributes e = new TestEntityNoAttributes("1");
   5:     TestEntityNoAttributes eCloned = e.DeepClone();
   6:     Assert.AreEqual(e.PublicField, eCloned.PublicField);
   7: }
   8:  
   9: [TestMethod]
  10: public void TestEntityAttributeDeepClone()
  11: {
  12:     TestEntityAttributes e = new TestEntityAttributes("1", "2", "3");
  13:     TestEntityAttributes eCloned = e.DeepClone();
  14:     Assert.AreEqual(e.PublicField, eCloned.PublicField);
  15:     Assert.AreEqual(e.ProtectedField, eCloned.ProtectedField);
  16:     Assert.AreEqual(e.PrivateField, eCloned.PrivateField);
  17: }

 

Naturally using both those methods you incur in performance penalty...but hey...this is the quick and dirty way after all.

分享到:
评论

相关推荐

    C#中Clone一个对象的值到另一个对象案例 c#经典案例.pdf

    在上面的代码中,我们创建了一个 A 对象 t1,然后使用 Clone 方法将其复制到另一个对象 t2 中。我们可以看到,t2 中的字段值都是 t1 的副本。然后,我们修改了 t2 中的字段值,但 t1 中的字段值保持不变。 结论 在...

    Object-Oriented Analysis and Design 第六章

    Object Oriented Analysis and Design 10Builder - MotivationThe Builder pattern separates the construction of a complex object from its representation so that the same construction process can create ...

    Jlink V8固件升级提示Clone的解决方法!

    “the emulator is JLink-Clone, the segger software only support orginal segger device” 然后闪退,IDE崩溃关闭! 解决方案: 1.升级压缩包里的固件(该固件将SN修改为默认的-1)。 2.进入J-Link Commander,...

    java Clone

    Java中的`clone`方法是Java语言提供的一种复制对象的方式,它允许创建一个对象的副本,这个副本与原对象具有相同的属性值,但它们是两个独立的对象,修改副本不会影响原对象。`clone`方法存在于Java的`java.lang....

    浅析Java中clone()方法浅克隆与深度克隆

    Java中的克隆(Clone)机制是面向对象编程中一种创建对象副本的方法,它允许程序员创建一个已有对象的新实例,新实例的数据与原对象相同。在Java中,克隆分为两种类型:浅克隆(Shallow Clone)和深度克隆(Deep ...

    深入理解JavaScript中的对象复制(Object Clone)

    可以通过在Object.prototype上添加一个clone方法来实现深复制。自定义的clone方法会检查对象的属性类型,并对不同类型的属性进行相应的处理: ```javascript Object.prototype.clone = function() { var copy = ...

    clone()方法示例(对象克隆)_对象克隆_nervouse78_源码

    在Java编程语言中,`clone()`方法是一个非常重要的概念,特别是在处理对象复制和数据持久化时。本示例将深入探讨`clone()`方法的工作原理、使用场景以及如何在实际编程中应用。首先,我们来理解一下`clone()`方法的...

    clone 深度克隆对象

    在Java中,实现深度克隆通常有两种方式:一是通过实现Cloneable接口并重写Object类的clone()方法;二是使用序列化和反序列化技术。前者需要特别注意的是,只有实现了Cloneable接口的类才能调用默认的clone()方法,...

    clone()示例源码

    在Java编程语言中,`clone()`方法是一个非常重要的概念,特别是在处理对象复制和克隆时。这个方法源自`Object`类,是所有Java类的基类。`clone()`的使用通常涉及到深度复制和浅复制的概念,这两者在数据结构和内存...

    java_clone用法

    在Java中,`clone`方法为我们提供了一个快速复制对象的方式。通过理解和掌握浅拷贝与深拷贝的概念,我们可以根据具体需求选择合适的方法来实现对象的复制。当涉及到引用类型的复制时,需要特别注意是否需要实现深...

    Jlink-clone解决办法,替换文件.rar

    2. **解压文件**:将“方法2.rar”压缩包解压到一个安全的位置。这通常包含一个或多个.exe可执行文件,这些文件可能用于更新Jlink-clone的固件,或者替换驱动程序。 3. **识别设备**:在设备管理器中找到Jlink-...

    java clone的小例子

    在Java编程语言中,`clone()`方法是一个非常重要的概念,特别是在对象复制和克隆方面。这个小例子将帮助初学者理解如何在Java中使用`clone()`来创建对象的副本。让我们深入探讨`clone()`方法以及它在实际编程中的...

    MapReduce-based Assembly Clone Search for Reverse Engineering.pdf

    An effective and efficient assembly code clone search engine can greatly reduce the effort of this process, since it can identify the cloned parts that have been previously analyzed. The assembly ...

    深化理解JavaScript中的对象复制(Object Clone)_.docx

    2. **自定义`clone()`方法**:我们可以为对象添加一个`clone()`方法,递归地复制所有属性。 ```javascript Object.prototype.clone = function() { var copy = (this instanceof Array) ? [] : {}; for (let attr...

    Clone详解.doc

    Java中的克隆(Clone)机制是一种创建对象副本的方法,它允许程序员复制一个对象的状态,而不会影响原始对象。克隆在编程中常用于创建对象的独立副本,使得新副本与原对象之间相互独立,对其中一个对象的修改不会...

    YOLOv10-DeepSORT-main

    This repository contains code for object detection and tracking in videos using the YOLOv10 object detection model and the DeepSORT algorithm. ## Installation 1. Clone this repository: ``` git ...

    java object 之clone方法全面解析

    Java中的`clone()`方法是Object类的一个成员方法,它提供了创建一个对象副本的功能。这篇文章将深入探讨`clone()`方法的工作原理、使用场景以及浅拷贝(shallow clone)与深拷贝(deep clone)的区别。 首先,让...

    java clone

    这个方法是Object类的一个成员,因此所有的Java类都默认拥有`clone`方法。不过,需要注意的是,`clone`方法并不执行深拷贝,也就是说,如果对象中包含引用类型的属性,这些引用指向的内存区域是共享的,不是完全独立...

Global site tag (gtag.js) - Google Analytics