Allix
Allix

Reputation: 170

C# - Call/write a deserialization method in another class

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

Answers (1)

Matthew Watson
Matthew Watson

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

Related Questions