Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
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.
I think the simpliest way to serialize and deserialize an object is to use a static class with the following two methods. We need also a class named StringWriterWithEncoding to set the Encoding of the XML string, because the Encoding property of the standard StringWriter class is readonly. (found here: http://devproj20.blogspot.com/2008/02/writing-xml-with-utf-8-encoding-using.html)
public static class GenericXmlSerializer
public static string Serialize<T>(T obj, Encoding encoding)
XmlSerializer serializer = new XmlSerializer(typeof(T));
TextWriter textWriter = new StringWriterWithEncoding(new StringBuilder(), encoding);
serializer.Serialize(textWriter, obj);
return textWriter.ToString();
public static T Deserialize<T>(string xml)
XmlSerializer serializer = new XmlSerializer(typeof(T));
TextReader textReader = new StringReader(xml);
return (T)serializer.Deserialize(textReader);
public class StringWriterWithEncoding : StringWriter
Encoding encoding;
public StringWriterWithEncoding(StringBuilder builder, Encoding encoding)
: base(builder)
this.encoding = encoding;
public override Encoding Encoding
get { return encoding; }
Usage:
//serialize
MyClass myClass = new MyClass();
string xml = GenericXmlSerializer.Serialize<MyClass>(myClass, Encoding.Unicode);
//deserialize
MyClass myClass2 = GenericXmlSerializer.Deserialize<MyClass>(xml);
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="toSerialize">To serialize.</param>
/// <returns></returns>
public static string SerializeObjectToXml<T>(this T toSerialize)
XmlSerializer xmlSerializer = new XmlSerializer(toSerialize.GetType());
StringWriter textWriter = new StringWriter();
xmlSerializer.Serialize(textWriter, toSerialize);
return textWriter.ToString();
/// <summary>
/// Serializes the object.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="toSerialize">To serialize.</param>
/// <param name="path">The path.</param>
public static void SerializeObjectToFile<T>(this T toSerialize, string path)
string xml = SerializeObjectToXml<T>(toSerialize);
using (StreamWriter sw = new StreamWriter(path, false))
sw.Write(xml);
/// <summary>
/// Deserializes the specified XML.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xml">The XML.</param>
/// <returns></returns>
public static T DeserializeFromXml<T>(this T original, string xml)
XmlSerializer serializer = new XmlSerializer(typeof(T));
TextReader textReader = new StringReader(xml);
return (T)serializer.Deserialize(textReader);
/// <summary>
/// Deserializes the specified object.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="original">The original.</param>
/// <param name="path">The path.</param>
/// <returns></returns>
public static T DeserializeFromFile<T>(this T original, string path)
string xml = string.Empty;
using (StreamReader sr = new StreamReader(path))
xml = sr.ReadToEnd();
return DeserializeFromXml<T>(original, xml);
Usage to serialize:
YourClassType obj = new YourClassType();
List<YourClassType> obj = new List<YourClassType>();
string xml = obj.SerializeObjectToXml();
obj.SerializeObjectToFile("PathToYourFile"); // It will save a file with your classes serialized (works with everything with the [Serializable] attribute).
Usage to deserialize:
YourClassType obj = new YourClassType().DeserializeFromXml("XML string here");
List<YourClassType> obj = new List<YourClassType>().DeserializeFromFile("XML string here");
YourClassType obj = new YourClassType().DeserializeFromFile("PathToYourFile");
And you have it running :)
I prefer extension methods because it allows you to have your code very clean, this works with every kind of object type you have, as far as it implements the [Serializable]
attribute on it.
If you need to specify how it will be serialized (as nodes or attributes), you can add the attribute on each of your properties such as:
[XmlElement("NameOfTheElementYouWant")]
[XmlAttribute("NameOfTheAttributeYouWant")]
[XmlText]
Hope this helps someone in the future.
Alejandro
Public Sub SaveToXML(ByVal outputFilename As String)
Dim xmls = New System.Xml.Serialization.XmlSerializer(Me.GetType)
Using sw = New IO.StreamWriter(outputFilename)
xmls.Serialize(sw, Me)
End Using
End Sub
Private tempState As Object = Me
Public Sub ReadFromXML(ByVal inputFilename As String)
Dim xmls = New System.Xml.Serialization.XmlSerializer(Me.GetType)
Using sr As New IO.StreamReader(inputFilename)
tempState = xmls.Deserialize(sr)
End Using
For Each pi In tempState.GetType.GetProperties()
Dim name = pi.Name
Dim realProp = (From p In Me.GetType.GetProperties
Where p.Name = name And p.MemberType = Reflection.MemberTypes.Property).Take(1)(0)
realProp.SetValue(Me, pi.GetValue(tempState, Nothing), Nothing)
End Sub
End Class
I can then simply use something like this:
Public Class ClientSettings
Inherits SerialisableClass
Public Property ZipExePath As String
Public Property DownloadPath As String
Public Property UpdateInstallPath As String
End Class
and call it like this:
Dim cs As New ClientSettings
cs.ReadFromXML("c:\myXMLfile.xml")
or even better (if I add the necessary constructor):
Dim cs as New ClientSettings("c:\myXMLFile.xml")
It seems nice and clean to me and works well in my situation.
Cheers
See XmlSerializer.Deserialize Method: You could create a static method like the following:
public static Options DeserializeFromFile(string filename) {
// Create an instance of the XmlSerializer specifying type and namespace.
XmlSerializer serializer = new XmlSerializer(typeof(Options));
// A FileStream is needed to read the XML document.
using (FileStream fs = new FileStream(filename, FileMode.Open)) {
XmlReader reader = new XmlTextReader(fs);
return (Options) serializer.Deserialize(reader);
} // using
The above can be called as:
Options foo = Options.DeserializeFromFile(@"C:\Options.xml");
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.