Customize a struct so that it serializes as a Int32
I save data using binary serialization. Now I have changed a field in the program from Int32 to a struct. But I still want to save the field as Int32 to be backward compatible. How do I do that?
background information My program is ported from Delphi and uses a lot of arrays. The problem is that the lists in Delphi start counting from 1, vilkort has made it dif开发者_如何学Goficult to keep track of the indexes when I am now developing in C#.So I use a struct to make it easier to deal with the 1-based index of the 0-based arrays until I have corrected the whole program.
The code
public void Save()
{
using (var writer = File.Open(Path, FileMode.Create))
{
var serializer = new BinaryFormatter();
serializer.Serialize(writer, _data);
}
}
private void Load()
{
using (var reader = File.Open(Path, FileMode.Open))
{
var deserializer = new BinaryFormatter();
_data = (Foo) deserializer.Deserialize(reader);
}
}
public struct Indexer
{
//0-baserat index
private int _index;
public Indexer(int index)
{
_index = index;
}
static public implicit operator Indexer(int index)
{
return new Indexer(index);
}
static public implicit operator int(Indexer indexer)
{
return indexer._index;
}
public override string ToString()
{
return (_index + 1).ToString();
}
...
}
You can add a legacy field of Int32 type, and also have the struct field. Make a method with the [OnDeserialized] attribute (and the correct arguments) and initialize the struct field from the int field under some circumstances, for example that the int field is nonzero and the struct has default value after deserialization, indicating that the data is from the older format.
private int intValue; // Legacy field
private SomeStruct structValue; // New field
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
if (intValue != 0)
{
// Old format, initialize struct with int value.
structValue = new SomeStruct(intValue);
}
}
This is not exactly elegant and there are other ways, but if you don't mind keeping two fields this is one of the simpler ways. Note that the above code assumes that zero indicates a "missing" value for the old int field.
I guess the only way will be to have two classes - one with the struct and one with int32. You could then convert one into the other after the serialzation. It is explicitly stated, that there is no backwards compatibility.
int n = YourStruct.SomeIntVar;
Marshal.WriteInt32(hBuffer, n);
I am not sure if this works for your case, as it depends on how you serialize your data into archives. In case you directly manipulate the data on memory or share memory (hBuffer), the above snippet should help.
ISerializerSurrogate
This will allow you control the serialization/deserialization process.
精彩评论