Reputation: 170
I'm trying to de-serialize a class in order to save user specific values (like a dirpath) in an XML-file.
Here's a snippet of my class:
[Serializable]
public class CustomSettings
{
public string initPath;
public string InitPath => initPath;
}
Both the serialization and deserialization work perfectly fine if I do this inside my MainWindow
class:
CustomSettings cs = new CustomSettings();
XmlSerializer mySerializer = new XmlSerializer(typeof(CustomSettings));
StreamWriter myWriter = new StreamWriter(@"U:\Alex\prefs.xml");
mySerializer.Serialize(myWriter, cs);
myWriter.Close();
And for the deserialization:
CustomSettings cs = new CustomSettings();
XmlSerializer _mySerializer = new XmlSerializer(typeof(CustomSettings));
FileStream myFstream = new FileStream(@"U:\Alex\prefs.xml", FileMode.Open);
cs = (CustomSettings)_mySerializer.Deserialize(myFstream);
myFstream.Close();
Now since I need to do the de-serialization a few times, I figured I write two methods which will do the above work, but due to readability I want them to be inside another class.
In MainWindow
I call this method inside another class, which again, works as intended:
public void WriteSettingsToFile(CustomSettings cs)
{
XmlSerializer mySerializer = new XmlSerializer(typeof(CustomSettings));
StreamWriter myWriter = new StreamWriter(@"U:\Alex\prefs.xml");
mySerializer.Serialize(myWriter, cs);
myWriter.Close();
}
The de-serialization function I wrote does not work, though. It loads the file successfully, returning the correct path value but as soon as it returns to the calling class, the string is always null. I rewrote the method several times, trying void, non-void returning a string, static etc. but I'm stuck.
Any help and ideas are appreciated!
Edit: Here's one of the tries with the deserialization method:
public void GetInitPath(CustomSettings cs)
{
XmlSerializer _mySerializer = new XmlSerializer(typeof(CustomSettings));
FileStream myFstream = new FileStream(@"U:\Alex\prefs.xml", FileMode.Open);
cs = (CustomSettings)_mySerializer.Deserialize(myFstream);
myFstream.Close();
}
Edit 2:
With the help of Matthew Watson I was able to solve my problem.
public void GetInitPath(ref CustomSettings cs)
{
XmlSerializer serializer = new XmlSerializer(typeof(CustomSettings));
using (var myFstream = new FileStream(@"U:\Alex\prefs.xml", FileMode.Open))
{
cs = (CustomSettings)serializer.Deserialize(myFstream);
}
}
Upvotes: 2
Views: 627
Reputation: 109762
This is your method that doesn't work:
public void GetInitPath(CustomSettings cs)
{
XmlSerializer _mySerializer = new XmlSerializer(typeof(CustomSettings));
FileStream myFstream = new FileStream(@"U:\Alex\prefs.xml", FileMode.Open);
cs = (CustomSettings)_mySerializer.Deserialize(myFstream);
myFstream.Close();
}
The problem with this method is that it DOESN'T RETURN THE RESULT.
It overwrites the reference to cs
that is passed to GetInitPath()
with a reference to the object returned from .Deserialise()
, but that does NOT change the original object passed to GetInitPath()
.
The solution is either to declare the parameter as a ref
parameter, or (much better) change the method to return the result like so:
public CustomSettings GetInitPath()
{
XmlSerializer _mySerializer = new XmlSerializer(typeof(CustomSettings));
FileStream myFstream = new FileStream(@"U:\Alex\prefs.xml", FileMode.Open);
var cs = (CustomSettings)_mySerializer.Deserialize(myFstream);
myFstream.Close();
return cs;
}
Another observation: It's better to use using
when possible to wrap resources that are disposable. If you do that, your method would look like this:
public CustomSettings GetInitPath()
{
var serializer = new XmlSerializer(typeof(CustomSettings));
using (var myFstream = new FileStream(@"U:\Alex\prefs.xml", FileMode.Open))
{
return (CustomSettings) serializer.Deserialize(myFstream);
}
}
This will close myFstream
even if an exception occurs in Deserialize()
.
Upvotes: 1