944,116 Members | Top Members by Rank

Ad:
  • C# Discussion Thread
  • Unsolved
  • Views: 29356
  • C# RSS
Jan 5th, 2006
0

XML Serialization

Expand Post »
How would I go about making this entire class Serializable?

What code would I add to a second constructor that would restore state/values from the XML file (de-serialize)?

C# Syntax (Toggle Plain Text)
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4.  
  5. namespace tgreer
  6. {
  7. public class indexer
  8. {
  9. private Dictionary<string, Int32> _documents;
  10. private Dictionary<string, Int32> _pages;
  11.  
  12. public indexer()
  13. {
  14. // class constructor
  15. _documents = new Dictionary<string, Int32>(250);
  16. _pages = new Dictionary<string, Int32>(1000);
  17. }
  18.  
  19. public void addDocIndex(string _seq, Int32 _offset)
  20. {
  21. _documents.Add(_seq, _offset);
  22.  
  23. }
  24.  
  25. public void addPageIndex(string _seq, Int32 _offset)
  26. {
  27. _pages.Add(_seq, _offset);
  28.  
  29. }
  30. }
  31. }

There are just two private dictionaries. The application which uses this class library will add values to the dictionaries by calling the public methods. I need a way to persist any values of a particular instance of this class/object, and to potentially restore them if the proper constructor is called.
Similar Threads
Team Colleague
Reputation Points: 227
Solved Threads: 37
Made Her Cry
tgreer is offline Offline
1,697 posts
since Dec 2004
Jan 5th, 2006
0

Re: XML Serialization

Here's my first attempt, for any following along:

C# Syntax (Toggle Plain Text)
  1. using System;
  2. using System.IO;
  3. using System.Collections.Generic;
  4. using System.Xml;
  5. using System.Xml.Serialization;
  6.  
  7. namespace tgreer
  8. {
  9. [XmlRoot("indexer")]
  10. public class indexer
  11. {
  12. [XmlElement("documents")]
  13. private Dictionary<string, Int32> _documents;
  14.  
  15. [XmlElement("pages")]
  16. private Dictionary<string, Int32> _pages;
  17.  
  18. public indexer()
  19. {
  20. // class constructor
  21. _documents = new Dictionary<string, Int32>(250);
  22. _pages = new Dictionary<string, Int32>(1000);
  23. }
  24. public void addDocIndex(string _seq, Int32 _offset)
  25. {
  26. _documents.Add(_seq, _offset);
  27.  
  28. }
  29.  
  30. public void addPageIndex(string _seq, Int32 _offset)
  31. {
  32. _pages.Add(_seq, _offset);
  33.  
  34. }
  35.  
  36. public void serializeMe()
  37. {
  38. // Serialization
  39. XmlSerializer s = new XmlSerializer(this.GetType());
  40. TextWriter w = new StreamWriter(@"c:\index.xml");
  41. s.Serialize(w, this);
  42. w.Close();
  43. }
  44. }
  45. }

It works, insofar as it creates an XML file. However, the dictionaries are not contained within it. Obviously I was hoping that two elements would be created, with child elements automatically generated for the key-value pairs within each dictionary. That'd be nice, I guess, but too much to hope for.

So I'll have to beef up the SerializeMe method to iterate through each dictionary, create XML elements/attributes within the loop.
Team Colleague
Reputation Points: 227
Solved Threads: 37
Made Her Cry
tgreer is offline Offline
1,697 posts
since Dec 2004
Jan 13th, 2006
0

Re: XML Serialization

the dictionaries are not serialized as they are private. Serializers only work on public properties/fields and even read onlys have problem. In laymans terms for an object to deserialize it basically creates a new object and writes the values back to it. For an object to do this to another object then the fields/properties have to be public. If you have a read only field then you have to be able to fill it in the constructor.

Hope it helps
One messy way around this is create public properties but limit the changes of values in the property set method, but as i said it gets messy
Reputation Points: 26
Solved Threads: 11
Posting Whiz in Training
f1 fan is offline Offline
275 posts
since Jan 2006
Jan 13th, 2006
0

Re: XML Serialization

I ended up using standard serialization instead of xml serialization. Also, I used a List instead of Dictionaries... I made a class for the items I wanted to store in the list, then serialized the List object.
Team Colleague
Reputation Points: 227
Solved Threads: 37
Made Her Cry
tgreer is offline Offline
1,697 posts
since Dec 2004
Jan 13th, 2006
0

Re: XML Serialization

Yeah i have been down a similar path (though i still used dictionaries but subclassed them) and used serialization and .net remoting instead of web services just to get round some issues. Hopefully in the future it will be solved as i dont see the point of not being able to fully serialize something without exposing all your private properties.
Reputation Points: 26
Solved Threads: 11
Posting Whiz in Training
f1 fan is offline Offline
275 posts
since Jan 2006
Jan 13th, 2006
0

Re: XML Serialization

The main problem I had with Dictionaries is there is no .IndexOf property. I not only had to retrieve a value from the dictionary via a key, but the "next" value as well.

List has an .IndexOf property. The problem is, in a List of Objects, you have to pass in the full object to get a match. The "Find" method is nice, but it took awhile to figure out the Predictor mechanism.
Team Colleague
Reputation Points: 227
Solved Threads: 37
Made Her Cry
tgreer is offline Offline
1,697 posts
since Dec 2004
Jan 13th, 2006
0

Re: XML Serialization

Yeah. I usually make use of foreaching through the keyvaluepair. But that is why i subclassed the generic dictionary so i could do what you wanted. I basically took the keys and values collection and copied them to an array and indexed it that way. I also wrote an append method to add from another list/dictionary into that one by passing it in. It got messy but i needed the key value pair more than anything so the list was out
Reputation Points: 26
Solved Threads: 11
Posting Whiz in Training
f1 fan is offline Offline
275 posts
since Jan 2006
Jan 13th, 2006
0

Re: XML Serialization

But you can put anything in a List, including a complete Object. So, you can make a Class that exposes the properties you need (like a key and a value). Mark the class [Serializable]. Then, make a List of that <class> type.

Heck, I'll just show you the whole thing. Two classes, Document and Pages. The idea is that another program parses a large PostScript file, finding the start of each document and each page. Later, I need to recreate this index in order to randomly retrieve any document or page. So, this class has two contstructors, the original which is used to create the index information, and another to de-serialize the previous values:

C# Syntax (Toggle Plain Text)
  1. using System;
  2. using System.IO;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Runtime.Serialization;
  6. using System.Runtime.Serialization.Formatters.Binary;
  7.  
  8. namespace TGREER
  9. {
  10. [Serializable]
  11. public class Document
  12. {
  13. private string _seq;
  14. private Int32 _offset;
  15.  
  16. public Document(string _seq, Int32 _offset)
  17. {
  18. this._seq = _seq;
  19. this._offset = _offset;
  20. }
  21.  
  22. public override string ToString()
  23. {
  24. return _seq;
  25. }
  26.  
  27. public string GenericSequenceNo
  28. {
  29. get { return _seq; }
  30. set { _seq = value; }
  31. }
  32.  
  33. public Int32 ByteOffset
  34. {
  35. get { return _offset; }
  36. set { _offset = value; }
  37. }
  38. }
  39.  
  40. [Serializable]
  41. public class Page
  42. {
  43. private string _seq;
  44. private Int32 _offset;
  45.  
  46. public Page(string _seq, Int32 _offset)
  47. {
  48. this._seq = _seq;
  49. this._offset = _offset;
  50. }
  51.  
  52. public override string ToString()
  53. {
  54. return _seq;
  55. }
  56.  
  57. public string GenericSequenceNo
  58. {
  59. get { return _seq; }
  60. set { _seq = value; }
  61. }
  62.  
  63. public Int32 ByteOffset
  64. {
  65. get { return _offset; }
  66. set { _offset = value; }
  67. }
  68. }
  69.  
  70. public class Indexer
  71. {
  72. private string _psFilename;
  73. private string _key;
  74.  
  75. private List<Document> _documents;
  76. private List<Page> _pages;
  77.  
  78. private Document _document;
  79. private Page _page;
  80.  
  81. // constructor, creates empty lists
  82. public Indexer(string _filename)
  83. {
  84. _psFilename = _filename;
  85. _documents = new List<Document>();
  86. _pages = new List<Page>();
  87. }
  88.  
  89. // constructor, re-creates lists from serialized files
  90. public Indexer(string _filename, string _docName, string _pgName)
  91. {
  92. _psFilename = _filename;
  93.  
  94. FileStream _s = new FileStream(_docName, FileMode.Open);
  95. BinaryFormatter formatter = new BinaryFormatter();
  96. _documents = (List<Document>)formatter.Deserialize(_s);
  97. _s.Close();
  98.  
  99. _s = new FileStream(_pgName, FileMode.Open);
  100. formatter = new BinaryFormatter();
  101. _pages = (List<Page>)formatter.Deserialize(_s);
  102. _s.Close();
  103. }
  104.  
  105. // public method to add entry to documents list
  106. public void addDocIndex(string _seq, Int32 _offset)
  107. {
  108. _document = new Document(_seq, _offset);
  109. _documents.Add(_document);
  110. }
  111.  
  112. // public method to add entry to pages list
  113. public void addPageIndex(string _seq, Int32 _offset)
  114. {
  115. _page = new Page(_seq, _offset);
  116. _pages.Add(_page);
  117. }
  118.  
  119. // public method to serialize list contents to named files
  120. public void serialize(string _docName, string _pgName)
  121. {
  122. FileStream _s = new FileStream(_docName, FileMode.Create);
  123. BinaryFormatter formatter = new BinaryFormatter();
  124. formatter.Serialize(_s, _documents);
  125. _s.Close();
  126.  
  127. _s = new FileStream(_pgName, FileMode.Create);
  128. formatter = new BinaryFormatter();
  129. formatter.Serialize(_s, _pages);
  130. _s.Close();
  131. }
  132.  
  133. // public method to return a string containing a document
  134. public string getDocument(string _key)
  135. {
  136. this._key = _key;
  137. _document = _documents.Find(isKey);
  138.  
  139. Int32 _i = _documents.IndexOf(_document);
  140. Int32 _byteStart = _document.ByteOffset;
  141. Int32 _byteEnd = _documents[_i + 1].ByteOffset - 1;
  142. Int32 _bytesToRead = _byteEnd - _byteStart;
  143.  
  144. FileStream _s = new FileStream(_psFilename, FileMode.Open);
  145. StreamReader _sr = new StreamReader(_s);
  146. _s.Seek(_byteStart, SeekOrigin.Begin);
  147.  
  148. char[] _buffer = new char[_bytesToRead];
  149. Int32 _bytesRead = _sr.ReadBlock(_buffer, 0, _bytesToRead);
  150. _s.Close();
  151.  
  152. return new string(_buffer);
  153. }
  154.  
  155. // public method to return a string containing a page
  156. public string getPage(string _key)
  157. {
  158. this._key = _key;
  159. _page = _pages.Find(isKey);
  160.  
  161. Int32 _i = _pages.IndexOf(_page);
  162. Int32 _byteStart = _page.ByteOffset;
  163. Int32 _byteEnd = _pages[_i + 1].ByteOffset - 1;
  164. Int32 _bytesToRead = _byteEnd - _byteStart;
  165.  
  166. FileStream _s = new FileStream(_psFilename, FileMode.Open);
  167. StreamReader _sr = new StreamReader(_s);
  168. _s.Seek(_byteStart, SeekOrigin.Begin);
  169.  
  170. char[] _buffer = new char[_bytesToRead];
  171. Int32 _bytesRead = _sr.ReadBlock(_buffer, 0, _bytesToRead);
  172. _s.Close();
  173.  
  174. return new string(_buffer);
  175.  
  176. }
  177.  
  178. // Predicate used for searching the List. Presumably, this is optimized so is faster than a forall loop?
  179. private bool isKey(Document _d)
  180. {
  181. if (_d.GenericSequenceNo == this._key)
  182. {
  183. return true;
  184. }
  185. else
  186. {
  187. return false;
  188. }
  189. }
  190.  
  191. private bool isKey(Page _p)
  192. {
  193. if (_p.GenericSequenceNo == this._key)
  194. {
  195. return true;
  196. }
  197. else
  198. {
  199. return false;
  200. }
  201. }
  202. }
  203. }
Team Colleague
Reputation Points: 227
Solved Threads: 37
Made Her Cry
tgreer is offline Offline
1,697 posts
since Dec 2004

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C# Forum Timeline: Newbie question:Unable to pass reference to an object
Next Thread in C# Forum Timeline: Problem deserializing objects from multiple classes





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC