User Name Password Register
DaniWeb IT Discussion Community
All
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
Reply
Join Date: Dec 2004
Posts: 1,590
Reputation: tgreer is an unknown quantity at this point 
Rep Power: 7
Solved Threads: 35
Colleague
tgreer tgreer is offline Offline
Made Her Cry

XML Serialization

  #1  
Jan 5th, 2006
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)?

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.
AddThis Social Bookmark Button
Reply With Quote  
Join Date: Dec 2004
Posts: 1,590
Reputation: tgreer is an unknown quantity at this point 
Rep Power: 7
Solved Threads: 35
Colleague
tgreer tgreer is offline Offline
Made Her Cry

Re: XML Serialization

  #2  
Jan 5th, 2006
Here's my first attempt, for any following along:

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.
Reply With Quote  
Join Date: Jan 2006
Location: Its the internet... i am everywhere lol
Posts: 274
Reputation: f1 fan is an unknown quantity at this point 
Rep Power: 3
Solved Threads: 10
f1 fan f1 fan is offline Offline
Posting Whiz in Training

Re: XML Serialization

  #3  
Jan 13th, 2006
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
Reply With Quote  
Join Date: Dec 2004
Posts: 1,590
Reputation: tgreer is an unknown quantity at this point 
Rep Power: 7
Solved Threads: 35
Colleague
tgreer tgreer is offline Offline
Made Her Cry

Re: XML Serialization

  #4  
Jan 13th, 2006
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.
Reply With Quote  
Join Date: Jan 2006
Location: Its the internet... i am everywhere lol
Posts: 274
Reputation: f1 fan is an unknown quantity at this point 
Rep Power: 3
Solved Threads: 10
f1 fan f1 fan is offline Offline
Posting Whiz in Training

Re: XML Serialization

  #5  
Jan 13th, 2006
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.
Reply With Quote  
Join Date: Dec 2004
Posts: 1,590
Reputation: tgreer is an unknown quantity at this point 
Rep Power: 7
Solved Threads: 35
Colleague
tgreer tgreer is offline Offline
Made Her Cry

Re: XML Serialization

  #6  
Jan 13th, 2006
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.
Reply With Quote  
Join Date: Jan 2006
Location: Its the internet... i am everywhere lol
Posts: 274
Reputation: f1 fan is an unknown quantity at this point 
Rep Power: 3
Solved Threads: 10
f1 fan f1 fan is offline Offline
Posting Whiz in Training

Re: XML Serialization

  #7  
Jan 13th, 2006
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
Reply With Quote  
Join Date: Dec 2004
Posts: 1,590
Reputation: tgreer is an unknown quantity at this point 
Rep Power: 7
Solved Threads: 35
Colleague
tgreer tgreer is offline Offline
Made Her Cry

Re: XML Serialization

  #8  
Jan 13th, 2006
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:

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;
			}
		}
	}
}
Reply With Quote  
Reply

Only community members can participate in forum threads. You must register or log in to contribute.

DaniWeb C# Marketplace
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)

 

Thread Tools Display Modes

Similar Threads
Other Threads in the C# Forum

All times are GMT -4. The time now is 1:11 pm.
Forum system based on vBulletin Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
©2003 - 2008 DaniWeb® LLC