| | |
XML Serialization
Please support our C# advertiser: Intel Parallel Studio Home
![]() |
•
•
Join Date: Dec 2004
Posts: 1,655
Reputation:
Solved Threads: 35
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)?
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.
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)
using System; using System.Collections.Generic; using System.Text; namespace tgreer { public class indexer { private Dictionary<string, Int32> _documents; private Dictionary<string, Int32> _pages; public indexer() { // class constructor _documents = new Dictionary<string, Int32>(250); _pages = new Dictionary<string, Int32>(1000); } public void addDocIndex(string _seq, Int32 _offset) { _documents.Add(_seq, _offset); } public void addPageIndex(string _seq, Int32 _offset) { _pages.Add(_seq, _offset); } } }
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.
•
•
Join Date: Dec 2004
Posts: 1,655
Reputation:
Solved Threads: 35
Here's my first attempt, for any following along:
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.
C# Syntax (Toggle Plain Text)
using System; using System.IO; using System.Collections.Generic; using System.Xml; using System.Xml.Serialization; namespace tgreer { [XmlRoot("indexer")] public class indexer { [XmlElement("documents")] private Dictionary<string, Int32> _documents; [XmlElement("pages")] private Dictionary<string, Int32> _pages; public indexer() { // class constructor _documents = new Dictionary<string, Int32>(250); _pages = new Dictionary<string, Int32>(1000); } public void addDocIndex(string _seq, Int32 _offset) { _documents.Add(_seq, _offset); } public void addPageIndex(string _seq, Int32 _offset) { _pages.Add(_seq, _offset); } public void serializeMe() { // Serialization XmlSerializer s = new XmlSerializer(this.GetType()); TextWriter w = new StreamWriter(@"c:\index.xml"); s.Serialize(w, this); w.Close(); } } }
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.
•
•
Join Date: Jan 2006
Posts: 275
Reputation:
Solved Threads: 11
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
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
•
•
Join Date: Jan 2006
Posts: 275
Reputation:
Solved Threads: 11
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.
•
•
Join Date: Dec 2004
Posts: 1,655
Reputation:
Solved Threads: 35
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.
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.
•
•
Join Date: Jan 2006
Posts: 275
Reputation:
Solved Threads: 11
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
•
•
Join Date: Dec 2004
Posts: 1,655
Reputation:
Solved Threads: 35
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:
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)
using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; namespace TGREER { [Serializable] public class Document { private string _seq; private Int32 _offset; public Document(string _seq, Int32 _offset) { this._seq = _seq; this._offset = _offset; } public override string ToString() { return _seq; } public string GenericSequenceNo { get { return _seq; } set { _seq = value; } } public Int32 ByteOffset { get { return _offset; } set { _offset = value; } } } [Serializable] public class Page { private string _seq; private Int32 _offset; public Page(string _seq, Int32 _offset) { this._seq = _seq; this._offset = _offset; } public override string ToString() { return _seq; } public string GenericSequenceNo { get { return _seq; } set { _seq = value; } } public Int32 ByteOffset { get { return _offset; } set { _offset = value; } } } public class Indexer { private string _psFilename; private string _key; private List<Document> _documents; private List<Page> _pages; private Document _document; private Page _page; // constructor, creates empty lists public Indexer(string _filename) { _psFilename = _filename; _documents = new List<Document>(); _pages = new List<Page>(); } // constructor, re-creates lists from serialized files public Indexer(string _filename, string _docName, string _pgName) { _psFilename = _filename; FileStream _s = new FileStream(_docName, FileMode.Open); BinaryFormatter formatter = new BinaryFormatter(); _documents = (List<Document>)formatter.Deserialize(_s); _s.Close(); _s = new FileStream(_pgName, FileMode.Open); formatter = new BinaryFormatter(); _pages = (List<Page>)formatter.Deserialize(_s); _s.Close(); } // public method to add entry to documents list public void addDocIndex(string _seq, Int32 _offset) { _document = new Document(_seq, _offset); _documents.Add(_document); } // public method to add entry to pages list public void addPageIndex(string _seq, Int32 _offset) { _page = new Page(_seq, _offset); _pages.Add(_page); } // public method to serialize list contents to named files public void serialize(string _docName, string _pgName) { FileStream _s = new FileStream(_docName, FileMode.Create); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(_s, _documents); _s.Close(); _s = new FileStream(_pgName, FileMode.Create); formatter = new BinaryFormatter(); formatter.Serialize(_s, _pages); _s.Close(); } // public method to return a string containing a document public string getDocument(string _key) { this._key = _key; _document = _documents.Find(isKey); Int32 _i = _documents.IndexOf(_document); Int32 _byteStart = _document.ByteOffset; Int32 _byteEnd = _documents[_i + 1].ByteOffset - 1; Int32 _bytesToRead = _byteEnd - _byteStart; FileStream _s = new FileStream(_psFilename, FileMode.Open); StreamReader _sr = new StreamReader(_s); _s.Seek(_byteStart, SeekOrigin.Begin); char[] _buffer = new char[_bytesToRead]; Int32 _bytesRead = _sr.ReadBlock(_buffer, 0, _bytesToRead); _s.Close(); return new string(_buffer); } // public method to return a string containing a page public string getPage(string _key) { this._key = _key; _page = _pages.Find(isKey); Int32 _i = _pages.IndexOf(_page); Int32 _byteStart = _page.ByteOffset; Int32 _byteEnd = _pages[_i + 1].ByteOffset - 1; Int32 _bytesToRead = _byteEnd - _byteStart; FileStream _s = new FileStream(_psFilename, FileMode.Open); StreamReader _sr = new StreamReader(_s); _s.Seek(_byteStart, SeekOrigin.Begin); char[] _buffer = new char[_bytesToRead]; Int32 _bytesRead = _sr.ReadBlock(_buffer, 0, _bytesToRead); _s.Close(); return new string(_buffer); } // Predicate used for searching the List. Presumably, this is optimized so is faster than a forall loop? private bool isKey(Document _d) { if (_d.GenericSequenceNo == this._key) { return true; } else { return false; } } private bool isKey(Page _p) { if (_p.GenericSequenceNo == this._key) { return true; } else { return false; } } } }
![]() |
Similar Threads
- VB6 Serialization (Visual Basic 4 / 5 / 6)
- Delphi 2006 launch event (Pascal and Delphi)
Other Threads in the C# Forum
- Previous Thread: Newbie question:Unable to pass reference to an object
- Next Thread: Problem deserializing objects from multiple classes
| Thread Tools | Search this Thread |
.net access ado.net algorithm appportability array barchart bitmap box broadcast button buttons c# chat check checkbox client color combobox control conversion csharp custom database datagrid datagridview dataset datetime degrees development draganddrop drawing encryption enum event excel file files form format forms function gdi+ httpwebrequest image index input install java label list listbox listener mandelbrot math mouseclick mysql networking operator path photoshop picturebox pixelinversion post prime programming radians regex remote remoting resolved. richtextbox save saving serialization server sleep socket sql statistics stream string table tcp text textbox thread time timer treeview update usercontrol validation view visualstudio webbrowser windows winforms wpf xml






