complications with XML serialization

Please support our C# advertiser: Intel Parallel Studio Home
Thread Solved

Join Date: Mar 2008
Posts: 325
Reputation: Diamonddrake is a jewel in the rough Diamonddrake is a jewel in the rough Diamonddrake is a jewel in the rough 
Solved Threads: 39
Diamonddrake's Avatar
Diamonddrake Diamonddrake is offline Offline
Posting Whiz

complications with XML serialization

 
0
  #1
Sep 9th, 2009
In my project I had been using a set of arrays to hold some data, realized it was a bad design, so then I decided to create an object that holds all the relevant data, and add them to an arraylist, this work great except all the data was information that extended a complicated dynamic button. So then, since the button was a custom user control anyway. I just added the fields i needed to store to the button class its self and everything was simple and right with the world.

then I come to the problem of saving the date, XML serialization is the method of choice, but I have a problem, This would want to save ALL the public properties of the button, not just the custom ones, so I ask.

Is there a way to denote that just these X amount of properties be serialized without going through and overriding all the properties in the base class and and adding a bracket that asks for it to be omitted?

alternatively, say I created a class that just holds my data properties and had my button class additionally inherit from that. giving it those fields, would there be a way to just serialize the members gained from that 2nd inheritance? (since # only supports 1 baseclass I refer of course to a linear inheritance) even still I just don't think this is the solution, I just don't know how to go about this, Other than go back to a separate data object.
Last edited by Diamonddrake; Sep 9th, 2009 at 1:50 am.
Reply With Quote Quick reply to this message  
Join Date: Oct 2008
Posts: 2,612
Reputation: adatapost has much to be proud of adatapost has much to be proud of adatapost has much to be proud of adatapost has much to be proud of adatapost has much to be proud of adatapost has much to be proud of adatapost has much to be proud of adatapost has much to be proud of adatapost has much to be proud of adatapost has much to be proud of 
Solved Threads: 468
Moderator
adatapost's Avatar
adatapost adatapost is offline Offline
Posting Maven

Re: complications with XML serialization

 
0
  #2
Sep 9th, 2009
Do you want an alternative of XML serialization? Take a look at BinarySerialization
Failure is not fatal, but failure to change might be. - John Wooden
Reply With Quote Quick reply to this message  
Join Date: Feb 2009
Posts: 3,215
Reputation: sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of 
Solved Threads: 573
Sponsor
sknake's Avatar
sknake sknake is offline Offline
.NET Enthusiast

Re: complications with XML serialization

 
1
  #3
Sep 9th, 2009
No -- you either need to handle the reflection yourself, serialize all the data, or mark the members you want serialized. Here is how you can serialize the data yourself. This is on a form with two buttons:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Reflection;
  5. using System.Windows.Forms;
  6. using System.Xml.Serialization;
  7.  
  8. namespace daniweb
  9. {
  10. public partial class frmSerial2 : Form
  11. {
  12. private byte[] serializedData;
  13.  
  14. public frmSerial2()
  15. {
  16. InitializeComponent();
  17. }
  18.  
  19. private void button1_Click(object sender, EventArgs e)
  20. {
  21. ConcreteClass cc = new ConcreteClass();
  22. cc.BaseProperty1 = "abc";
  23. cc.BaseProperty2 = 5;
  24. cc.BaseProperty3 = DateTime.Now;
  25.  
  26. cc.Property1 = "ssss";
  27. cc.Property2 = 15;
  28. cc.Property3 = DateTime.Now.AddDays(5);
  29. cc.Property4 = 1324;
  30.  
  31. using (MemoryStream ms = new MemoryStream())
  32. {
  33. CustomSerializer.SerializeObject(ms, cc);
  34. serializedData = ms.ToArray();
  35. }
  36.  
  37. #region lets inspect our work
  38. {
  39. string xmlData = System.Text.ASCIIEncoding.UTF8.GetString(serializedData);
  40. Console.WriteLine(xmlData);
  41. System.Diagnostics.Debugger.Break();
  42. }
  43. #endregion
  44. }
  45.  
  46. private void button2_Click(object sender, EventArgs e)
  47. {
  48. ConcreteClass cc = new ConcreteClass();
  49. using (MemoryStream ms = new MemoryStream(serializedData))
  50. {
  51. ms.Position = 0;
  52. ms.Seek(0, SeekOrigin.Begin);
  53. CustomSerializer.DeserializeObject(ms, cc);
  54. }
  55. System.Diagnostics.Debugger.Break();
  56. }
  57. }
  58.  
  59. public class BaseClass
  60. {
  61. public string BaseProperty1 { get; set; }
  62. public int BaseProperty2 { get; set; }
  63. public DateTime BaseProperty3 { get; set; }
  64.  
  65. public BaseClass()
  66. {
  67. }
  68. }
  69.  
  70. public class ConcreteClass : BaseClass
  71. {
  72. [CustomSerialized]
  73. public string Property1 { get; set; }
  74. [CustomSerialized]
  75. public int Property2 { get; set; }
  76. [CustomSerialized]
  77. public DateTime Property3 { get; set; }
  78. public long Property4 { get; set; }
  79.  
  80. public ConcreteClass()
  81. : base()
  82. {
  83. }
  84. }
  85.  
  86. [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
  87. internal sealed class CustomSerialized : Attribute
  88. {
  89. public CustomSerialized()
  90. {
  91.  
  92. }
  93. }
  94.  
  95. public class NameValuePair
  96. {
  97. public string PropertyName { get; set; }
  98. public object PropertyValue { get; set; }
  99. public NameValuePair() { }
  100. public NameValuePair(string PropertyName, object PropertyValue)
  101. : this()
  102. {
  103. this.PropertyName = PropertyName;
  104. this.PropertyValue = PropertyValue;
  105. }
  106. }
  107.  
  108. public static class CustomSerializer
  109. {
  110.  
  111. //.DeclaredOnly - ignored inherited members
  112. private const BindingFlags SqlObjectBindingFlags = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
  113.  
  114. private static bool IsMarkedCustomSerialzed(PropertyInfo Prop)
  115. {
  116. Attribute[] attrs = System.Attribute.GetCustomAttributes(Prop);
  117. foreach (Attribute at in attrs)
  118. {
  119. if ((at as CustomSerialized) != null)
  120. return true;
  121. }
  122. return false;
  123. }
  124.  
  125. private static PropertyInfo[] GetProperties(object o)
  126. {
  127. List<PropertyInfo> result = new List<PropertyInfo>();
  128. PropertyInfo[] properties = o.GetType().GetProperties(SqlObjectBindingFlags);
  129. foreach (PropertyInfo pi in properties)
  130. {
  131. if (IsMarkedCustomSerialzed(pi) && pi.CanRead && pi.CanWrite)
  132. result.Add(pi);
  133. }
  134. return result.ToArray();
  135. }
  136.  
  137. public static void SerializeObject(Stream stream, object o)
  138. {
  139. PropertyInfo[] properties = GetProperties(o);
  140. List<NameValuePair> lst = new List<NameValuePair>();
  141. foreach (PropertyInfo pi in properties)
  142. {
  143. lst.Add(new NameValuePair(pi.Name, pi.GetValue(o, null)));
  144. }
  145. XmlSerializer ser = new XmlSerializer(typeof(List<NameValuePair>));
  146. ser.Serialize(stream, lst);
  147. }
  148.  
  149. //This doesn't create the object for you since we're not serializing all properties.
  150. //It basically does "apply property changes"
  151. public static void DeserializeObject(Stream s, object o)
  152. {
  153. XmlSerializer ser = new XmlSerializer(typeof(List<NameValuePair>));
  154. List<NameValuePair> lst = (List<NameValuePair>)ser.Deserialize(s);
  155. PropertyInfo[] properties = GetProperties(o);
  156. foreach (PropertyInfo pi in properties)
  157. {
  158. NameValuePair nvp = FindInList(lst, pi.Name);
  159. if (nvp != null)
  160. {
  161. pi.SetValue(o, nvp.PropertyValue, null);
  162. }
  163. }
  164. }
  165. private static NameValuePair FindInList(List<NameValuePair> searchList, string PropertyName)
  166. {
  167. foreach (NameValuePair nvp in searchList)
  168. {
  169. if (string.Compare(nvp.PropertyName, PropertyName, true) == 0)
  170. return nvp;
  171. }
  172. return null;
  173. }
  174. }
  175. }
Scott Knake
Custom Software Development
Apex Software, Inc.
Reply With Quote Quick reply to this message  
Join Date: Mar 2008
Posts: 325
Reputation: Diamonddrake is a jewel in the rough Diamonddrake is a jewel in the rough Diamonddrake is a jewel in the rough 
Solved Threads: 39
Diamonddrake's Avatar
Diamonddrake Diamonddrake is offline Offline
Posting Whiz

Re: complications with XML serialization

 
0
  #4
Sep 9th, 2009
Scott you never cease to amaze me! This is some great code, let me ask so questions to make sure I got it.

these Bindingflags allow you to tell the serializer to only serialize the public members declared in that object, not the inherited members?
--if so this is awesome.

and could this be modified to serialize a list of classes?

from what I can follow the data is saved just as pairs of property names and the values of each, so multiple objects that have the same property names... just not sure how I could handle that.

Thanks!
Reply With Quote Quick reply to this message  
Join Date: Feb 2009
Posts: 3,215
Reputation: sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of 
Solved Threads: 573
Sponsor
sknake's Avatar
sknake sknake is offline Offline
.NET Enthusiast

Re: complications with XML serialization

 
0
  #5
Sep 10th, 2009
>> these Bindingflags allow you to tell the serializer to only serialize the public members declared in that object, not the inherited members? --if so this is awesome.

Yes. This only does properties (have get/set, not fields).

>>and could this be modified to serialize a list of classes?

Yes. I almost always serialize List<class>

from what I can follow the data is saved just as pairs of property names and the values of each, so multiple objects that have the same property names... just not sure how I could handle that.

You can't have multiple property names the same. IE a button doesn't have two properties called "Text", it can only have a single property. The only exception to this is when you inherit a class you can override the member -- but regardless it is still a single property name/value pair. You can also hide inherited members with the new keyword, but again this doesn't apply.

The reason this doesn't apply is because you said you wanted to serialize X properties in a class and ignore inheritence so I cannot think of a single way where this would be a problem.
Scott Knake
Custom Software Development
Apex Software, Inc.
Reply With Quote Quick reply to this message  
Join Date: Mar 2008
Posts: 325
Reputation: Diamonddrake is a jewel in the rough Diamonddrake is a jewel in the rough Diamonddrake is a jewel in the rough 
Solved Threads: 39
Diamonddrake's Avatar
Diamonddrake Diamonddrake is offline Offline
Posting Whiz

Re: complications with XML serialization

 
0
  #6
Sep 10th, 2009
Thanks for the reply!

what i meant was, your serializer/dematerializer methods accept an object. but that object is expected to be a class with members, I need those functions to accept a list of objects. not just an object.

I can't seem to figure out how to get it to work right. I got a result, but the XML file is then fairly confusing and for some reason the resulting XML file's objects are always backwards, as in the last object in the list is first in the xml file.

  1. public static void SerializeObject(Stream stream, List<object> objlist)
  2. {
  3.  
  4. List<List<NameValuePair>> newObjList = new List<List<NameValuePair>>();
  5.  
  6. foreach (object o in objlist)
  7. {
  8. PropertyInfo[] properties = GetProperties(o);
  9. List<NameValuePair> lst = new List<NameValuePair>();
  10. foreach (PropertyInfo pi in properties)
  11. {
  12. lst.Add(new NameValuePair(pi.Name, pi.GetValue(o, null)));
  13. }
  14. newObjList.Add(lst);
  15. }
  16. //now I have a lists of lists right? now what do I do do I serialize each one separately then add the resulting stream to another serializer? I'm kind of at a loss. this serialization thing is new to me.
  17.  
  18. //or would I just serialize the list of lists and this actually work? like?
  19.  
  20. XmlSerializer ser = new XmlSerializer(typeof(List<List<NameValuePair>>));
  21. ser.Serialize(stream, newObjList);
  22. }

note, code is modified from the code you posted previously.

and as far as the deserialzing such a thing. I can't even get started.

-->a briefing of my final goal is to have a bar of dynamically created buttons with special values that need to be saved. then when the app opens back up i need it to parse the xml to return a list of objects that I can loop through and create a new special button for each one, assigning the special values to each one as it goes.

-->stuck in the mud at the first corner I'm afraid, but you did an amazing job getting me to the starting line.
Last edited by Diamonddrake; Sep 10th, 2009 at 5:49 pm.
Reply With Quote Quick reply to this message  
Join Date: Feb 2009
Posts: 3,215
Reputation: sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of sknake has much to be proud of 
Solved Threads: 573
Sponsor
sknake's Avatar
sknake sknake is offline Offline
.NET Enthusiast

Re: complications with XML serialization

 
0
  #7
Sep 10th, 2009
So mark the special's button class with the attribute I gave you and serialize the button. I don't understand the need for a double list.
Scott Knake
Custom Software Development
Apex Software, Inc.
Reply With Quote Quick reply to this message  
Join Date: Mar 2008
Posts: 325
Reputation: Diamonddrake is a jewel in the rough Diamonddrake is a jewel in the rough Diamonddrake is a jewel in the rough 
Solved Threads: 39
Diamonddrake's Avatar
Diamonddrake Diamonddrake is offline Offline
Posting Whiz

Re: complications with XML serialization

 
0
  #8
Sep 10th, 2009
because the buttons are not predefined. they are created dynamically by a user. I can't hardcode them. they will have to be added to a list upon creation. then multiple instances of this class will need to be serialized.

I can't seen any other way to do it besides serializing a list of lists!

am I wrong?
Reply With Quote Quick reply to this message  
Join Date: Mar 2008
Posts: 325
Reputation: Diamonddrake is a jewel in the rough Diamonddrake is a jewel in the rough Diamonddrake is a jewel in the rough 
Solved Threads: 39
Diamonddrake's Avatar
Diamonddrake Diamonddrake is offline Offline
Posting Whiz

Re: complications with XML serialization

 
0
  #9
Sep 11th, 2009
Alright! I figured it out. I modified your deserialize method to return a list of custom objects contains just the extra data members that will be marked in the extendedbutton control class that way I can loop through them and create my buttons form them. I used all concept code because I don't like practicing in my real projects but I decided I would post the result for learning purposes for future visitors to the site.

Thanks for everything sknake! without your help I'm not sure I could have done it.

modified deserialize method.

  1. public static List<extrabutondata> DeserializeObject(Stream s)
  2. {
  3. XmlSerializer ser = new XmlSerializer(typeof(List<List<NameValuePair>>));
  4. List<List<NameValuePair>> lst = (List<List<NameValuePair>>)ser.Deserialize(s);
  5.  
  6. List<extrabutondata> extralist = new List<extrabutondata>();
  7.  
  8. for (int i = 0; i < lst.Count; i++)
  9. {
  10. extrabutondata o = new extrabutondata();
  11.  
  12.  
  13. PropertyInfo[] properties = GetProperties(o);
  14. foreach (PropertyInfo pi in properties)
  15. {
  16. NameValuePair nvp = FindInList(lst[i], pi.Name);
  17. if (nvp != null)
  18. {
  19. pi.SetValue(o, nvp.PropertyValue, null);
  20. }
  21. }
  22.  
  23. extralist.Add(o);
  24. }
  25.  
  26. return extralist;
  27. }
  28. // and example type class it uses
  29. public class extrabutondata
  30. {
  31. public extrabutondata()
  32. {
  33.  
  34. }
  35. public string name {get; set;}
  36. public int number { get; set;}
  37. }

Thanks again! that's another Daniweb form post solved by Sknake!
Reply With Quote Quick reply to this message  
Reply

Tags
serialization, xml

This thread has been marked solved.
Perhaps start a new thread instead?
Message:



Similar Threads
Other Threads in the C# Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC