public class Options
{
public FolderOption FolderOption { set; get; }
public Options()
{
FolderOption = new FolderOption();
}
public void Save()
{
XmlSerializer serializer = new XmlSerializer(typeof(Options));
TextWriter textWriter = new StreamWriter(@"C:\Options.xml");
serializer.Serialize(textWriter, this);
textWriter.Close();
}
public void Read()
{
XmlSerializer deserializer = new XmlSerializer(typeof(Options));
TextReader textReader = new StreamReader(@"C:\Options.xml");
//this = (Options)deserializer.Deserialize(textReader);
textReader.Close();
}
}
}
I managed to Save without problem, all members of FolderOption are deserialized. But the problem is how to read it back? The line - //this = (Options)deserializer.Deserialize(textReader); won't work.
Edit: Any solution to this problem? Can we achieve the same purpose without assigning to this? That is deserialize Options object back into Option. I am lazy to do it property by property. Performing on the highest level would save of lot of effort.
Build your .Read()
method as a static function that returns the read object:
public static Options Read(string path)
{
XmlSerializer deserializer = new XmlSerializer(typeof(Options));
using (TextReader textReader = new StreamReader(path))
{
return (Options)deserializer.Deserialize(textReader);
}
}
Then change your calling code so rather than something like this:
Options myOptions = new Options();
myOptions.Read(@"C:\Options.xml");
You do something like this:
Options myOptions = Options.Read(@"C:\Options.xml");
The nice difference is that it's impossible to ever have an Options object that doesn't have some data behind it.
This will work if your Options type is a struct, as you can a alter a struct itself.
If Options is a class (reference type), you can't assign to the current instance of a reference type with in that instance. Suggesting you to write a helper class, and put your Read and Save methods there, like this
public class XmlSerializerHelper<T>
{
public Type _type;
public XmlSerializerHelper()
{
_type = typeof(T);
}
public void Save(string path, object obj)
{
using (TextWriter textWriter = new StreamWriter(path))
{
XmlSerializer serializer = new XmlSerializer(_type);
serializer.Serialize(textWriter, obj);
}
}
public T Read(string path)
{
T result;
using (TextReader textReader = new StreamReader(path))
{
XmlSerializer deserializer = new XmlSerializer(_type);
result = (T)deserializer.Deserialize(textReader);
}
return result;
}
}
And then consume it from your caller, to read and save objects, instead of trying it from the class.
//In the caller
var helper=new XmlSerializerHelper<Options>();
var obj=new Options();
//Write and read
helper.Save("yourpath",obj);
obj=helper.Read("yourpath");
And put the XmlSerializerHelper in your Util's namespace, it is reusable and will work with any type.
An object cannot deserialize itself, by definition: it already exists, and deserialization creates a new instance of the type.
It sometimes makes sense to create a new, empty instance of a class, then fill it in with information brought in from XML. The instance could also be "almost empty". You might do this, for instance, in order to load user preferences, or in general, to set the instance back up to the way it used to be. The "empty" or "near empty" state of the instance would be a valid state for the class: it just wouldn't know what state it used to be in before it was persisted.
Also, I recommend you get into the habit of implementing "using" blocks:
public void Save()
{
XmlSerializer serializer = new XmlSerializer(typeof(Options));
using (TextWriter textWriter = new StreamWriter(@"C:\Options.xml"))
{
serializer.Serialize(textWriter, this);
// no longer needed: textWriter.Close();
}
}
public void Read()
{
XmlSerializer deserializer = new XmlSerializer(typeof(Options));
using (TextReader textReader = new StreamReader(@"C:\Options.xml"))
{
// no longer needed: textReader.Close();
}
}
This will ensure that the TextReaders are disposed of even if an exception is thrown. That's why the Close calls are no longer needed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With