silverlight中的clone: Deep Clone of a business object: the quick and dirty way
2010-01-23 08:59
651 查看
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:
In Silverlight you can write something similar and use the DataContractSerializer and the xml serialization:
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:
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:
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:
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.
Naturally using both those methods you incur in performance penalty…but hey…this is the quick and dirty way after all.
http://www.primordialcode.com/index.php/2008/10/18/deep-clone-business-object-quick-dirty/
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.
http://www.primordialcode.com/index.php/2008/10/18/deep-clone-business-object-quick-dirty/
相关文章推荐
- The Future of Real-Time SLAM and Deep Learning vs SLAM
- custom format Property of business object for the data binding
- Deep Learning and the Triumph of Empiricism
- The Future of Client App Dev : WPF and Silverlight Convergence
- C++ for Artists: The Art, Philosophy, and Science of Object-Oriented Programming
- The development and prosperous of deep learning theory applying in computer vision(Image part)
- Mastering the game of Go with deep neural networks and tree search
- Theano-Deep Learning Tutorials 笔记:Modeling and generating sequences of polyphonic music with the RNN
- The Future of Real-Time SLAM and "Deep Learning vs SLAM"
- Bob Tarr: Some Object-Oriented Design Principles(1): Minimize The Accessibility of Classes and Members
- Automating the Creation of Data-Rich Business Documents with Word 2007 and Visual Basic 2005
- 深入解读AlphaGo,Nature-2016:Mastering the game of Go with deep neural networks and tree search
- The Search : How Google and Its Rivals Rewrote the Rules of Business and Transformed Our Culture
- illustrates the use of a DataView object to filter and sort rows
- A way to control the width of columns and bars (RDL)
- The Future of Real-Time SLAM and "Deep Learning vs SLAM" 深度学习与slam
- 论文笔记:Mastering the game of Go with deep neural networks and tree search
- About the Height and Width property of DisplayObject
- Automating the Creation of Data-Rich Business Documents with Word 2007 and ASP.NET
- AlphaGo论文的译文,用深度神经网络和树搜索征服围棋:Mastering the game of Go with deep neural networks and tree search