•
•
•
•
What is DaniWeb IT Discussion Community?
You're currently browsing the C# section within the Software Development category of DaniWeb, a massive community of 427,765 software developers, web developers, Internet marketers, and tech gurus who are all enthusiastic about making contacts, networking, and learning from each other. In fact, there are 3,671 IT professionals currently interacting right now! Registration is free, only takes a minute and lets you enjoy all of the interactive features of the site.
Please support our C# advertiser: Programming Forums
Views: 11758 | Replies: 7
![]() |
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)?
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.
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.
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
Location: Its the internet... i am everywhere lol
Posts: 274
Reputation:
Rep Power: 3
Solved Threads: 10
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
Location: Its the internet... i am everywhere lol
Posts: 274
Reputation:
Rep Power: 3
Solved Threads: 10
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.
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
Location: Its the internet... i am everywhere lol
Posts: 274
Reputation:
Rep Power: 3
Solved Threads: 10
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
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:
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;
}
}
}
}
![]() |
•
•
•
•
•
•
•
•
DaniWeb C# Marketplace
•
•
•
•
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
- VB6 Serialization (Visual Basic 4 / 5 / 6)
- Delphi 2006 launch event (Pascal and Delphi)
Other Threads in the C# Forum
- Previous Thread: Want Date Format in dd/mm/yyyy in ASP.Net With C#.
- Next Thread: Problem deserializing objects from multiple classes



Linear Mode