Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binary Formatter and properties with\without backing fields

I have the following class serialized into a file using BinaryFormatter:

[Serializable]
public class TestClass
{
    public String ItemTwo { get; set; }
    public String ItemOne { get; set; }
}

Using this code:

FileStream fs = new FileStream("DataFile.dat", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, new TestClass{ItemOne = "ItemOne", ItemTwo = "ItemTwo"});
fs.Close();

When deserializing using this code:

FileStream fs = new FileStream("DataFile.dat", FileMode.Open);
BinaryFormatter formatter = new BinaryFormatter();
TestClass addresses = (TestClass)formatter.Deserialize(fs);
fs.Close();

I get everything normally. However, now I need the class to have some backing fields like so:

[Serializable]
public class TestClass
{
    private string _itemTwo;
    private string _itemOne;

    public String ItemTwo
    {
        get { return _itemTwo; }
        set { _itemTwo = value; }
    }

    public String ItemOne
    {
        get { return _itemOne; }
        set { _itemOne = value; }
    }
}

My problem is that now, for some reason, deserialization from previous version doesn't work anymore. I get the class but the Properties are left null.
I cannot affect the serialization process, or the former class state.
How can I get the file to deserialize to the current class?

like image 621
atlanteh Avatar asked Apr 16 '15 13:04

atlanteh


People also ask

Is binary formatter safe?

The BinaryFormatter type is dangerous and is not recommended for data processing. Applications should stop using BinaryFormatter as soon as possible, even if they believe the data they're processing to be trustworthy. BinaryFormatter is insecure and can't be made secure.

How does binary formatter work?

BinaryFormatter is used to serialize an object (meaning it converts it to one long stream of 1s and 0s), and deserialize it (converting that stream back to its usual form with all data intact), and is typically used with to save data to the hard disk so it can be loaded again after the game is closed and started up ...

What is a binary formatter?

The class BinaryFormatter in C# performs the actions of “serialization” and “deserialization” of binary data. It takes simple data structures such as integers (int), decimal numbers (float), and collections of letters and numbers (string) and can convert them into a binary format.


1 Answers

If you try to serialize the first version of TestClass the backfields will be serialized automatically by the binary formatter. Auto properties are only syntactic sugar, the compiler transform them in normal properties with backing fields. If you decompile your original console application (or class library) with ILSpy for example you'll see that your private fields are declared as:

.field private string '<ItemOne>k__BackingField'

which is way different from your second declaration with backing fields which yields to:

.field private string _itemOne

An approach would be declaring the ISerializable interface on your TestClass and get the value of the original properties using the information contained in the class SerializationInfo

[Serializable]
public class TestClass : ISerializable
{
    private string _itemTwo;
    private string _itemOne;

    public String ItemTwo
    {
        get { return _itemTwo; }
        set { _itemTwo = value; }
    }

    public String ItemOne
    {
        get { return _itemOne; }
        set { _itemOne = value; }
    }

    protected TestClass(SerializationInfo info, StreamingContext context)
    {
        _itemTwo = info.GetString("<ItemTwo>k__BackingField");
        _itemOne = info.GetString("<ItemOne>k__BackingField");
    }

    [SecurityPermissionAttribute(SecurityAction.Demand,
    SerializationFormatter = true)]
    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        //Add data to your serialization process here
    }
}

so you tell the BinaryFormatter how you want your backing fields to be initialized during deserialization.

like image 197
codingadventures Avatar answered Sep 18 '22 18:09

codingadventures