Introduction
As serializing of a TreeNode
object does not work as it is said in the Microsoft’s online page, or other Web pages, e.g. Object Serialization using C# on this Web site.
If you try to write a class inherited from a TreeNode
object, you will find a NullPointerException
during serialization to/from the file. Your process crashes, and a wonderful and beautiful NullPointerException
is shown (if you've not caught it).
The reason is one, simple and not easy to reach: the TreeNode
object implements the ISerializable
interface but deserialization does not work very well, that's because you cannot simply serialize an object that inherits the TreeNode
and be able to [Serialize]
it.
You can find an example of the problem here. I did not write that code, but it's a great example, and in this article you can find how to resolve it.
So, if you try to write code like this:
[Serializable]
public class MyObject : TreeNode
{
public MyObject(string dirName) : base(dirName)
{
}
You will find that, one of the most simple code ever made will crash when you try to serialize and de-serialize the MyObject
object.
static void Main(string[] args)
{
MyObject obj = new MyObject("blabla");
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Create,
FileAccess.Write, FileShare.None);
formatter.Serialize(stream, obj);
stream.Close();
}
Don't worry, there is a SIMPLE and EASY solution, but it would be easier if [Serialize]
tag worked as it was supposed to (like Java). I think it's not necessarily a full project to show how it can be done, it's really very simple!
Background
I surfed the Internet, spending a lot of hours trying to find the answer for this problem in C#. Don’t worry, it does not exist anywhere but here. I found some objects that used TreeNode
and TreeView
as a base class, and derived it (and you had to derive that derived class, not very practical). I suggest that you inherit the TreeNode
class, because the TreeView
class is used only for GUI approaches (I must say it: use the Facade pattern, very easy and useful while using a memory-GUI duet).
But it was not what I wanted, and it was a lot of work to change my project, and mapping all my work to store it in an XML (so cool, so fantastic, …) but I wanted binary files.
What I wanted was to derive a TreeNode
, and store it to a binary or XML file, does not matter what the structure of my object was. At Microsoft's Web page was no answer, I tried to find it. And I won.
Using the Code
After a long time, I found the answer: you can derive your class from TreeNode
, but the serializing way works different from other classes (not to say Microsoft’s help). This is how I did it:
First of all, derive your class:
[Serializable]
public class DbVisioFile: TreeNode, …
{
private string mFilePath;
private string mOwner;
private string mSummary;
private string mDifferences;
private string mComments;
private Version mVersion;
After this, make your own Serialization
control-code:
#region Serialization control
protected DbVisioFile(SerializationInfo si, StreamingContext context)
: base(si, context)
{
this.FilePath = si.GetString("FilePath");
this.Owner = si.GetString("Owner");
this.Summary = si.GetString("Summary");
this.Differences = si.GetString("Differences");
this.Comments = si.GetString("Comments");
this.Version = new Version(si.GetString("Version"));
}
protected override void Serialize(SerializationInfo si, StreamingContext context)
{
base.Serialize(si, context);
si.AddValue("FilePath", this.FilePath);
si.AddValue("Owner", this.Owner);
si.AddValue("Summary", this.Summary);
si.AddValue("Differences", this.Differences);
si.AddValue("Comments", this.Comments);
si.AddValue("Version", this.Version.ToString());
}
#endregion
You can see that the code has no reason to work, but it does. It is a mixture of the ISerializable
and [Serializable]
point of view.
Points of Interest
In the overriding of the Serialize
method, the first line is:
base.Serialize(si, context);
As a result of this, the treenode
structure is serialized to disk.
You have to be very careful with calling the following line in the constructor code.
:base(si, context)
If It Was Useful To You...
... or if you have any questions, please send me an email at victoragus@yahoo.es with a clear question and the source code.
Remember, the beginnings are very hard. And if you work with a language that doesn't work as it is supposed to, it is even harder.
Sorry for my English
So sorry for my English, but if you are English, try to rewrite it in Spanish and send me. We both will have some laughs!
History
- 20th March, 2008: Initial post