IBinarySerializable Interface
Namespace: KGySoft.Serialization.BinaryAssembly: KGySoft.CoreLibraries (in KGySoft.CoreLibraries.dll) Version: 8.1.0
public interface IBinarySerializable
Public Interface IBinarySerializable
public interface class IBinarySerializable
type IBinarySerializable = interface end
Following example demonstrates the usage of the special constructor version.
using System;
using System.IO;
using KGySoft.Serialization.Binary;
// This is a simple sealed class that will never be derived
public sealed class ExampleSimple : IBinarySerializable
{
public int IntProp { get; }
public string StringProp { get; }
// this is the ordinary constructor
public ExampleSimple(int intValue, string stringValue)
{
IntProp = intValue;
StringProp = stringValue;
}
// this is the special constructor used by the deserializer
// if you have read-only fields you must implement this constructor
private ExampleSimple(BinarySerializationOptions options, byte[] serData)
{
using (BinaryReader reader = new BinaryReader(new MemoryStream(serData)))
{
IntProp = reader.ReadInt32();
bool isStringPropNull = reader.ReadBoolean();
StringProp = isStringPropNull ? null : reader.ReadString();
}
}
public byte[] Serialize(BinarySerializationOptions options)
{
MemoryStream ms = new MemoryStream();
using (BinaryWriter writer = new BinaryWriter(ms))
{
writer.Write(IntProp);
writer.Write(StringProp == null);
if (StringProp != null)
writer.Write(StringProp);
}
return ms.ToArray();
}
public void Deserialize(BinarySerializationOptions options, byte[] serData)
{
throw new InvalidOperationException("Will not be called because special constructor is implemented");
}
}
The following example introduces a pattern that can be used for serialization and deserialization serializable base and derived classes
and with versioned content (optional fields):
using System.IO;
using KGySoft.Serialization.Binary;
public class SerializableBase : IBinarySerializable
{
public int IntProp { get; set; }
public string StringProp { get; set; }
private static int currentVersionBase = 1;
// this is the ordinary constructor
public SerializableBase(int intValue, string stringValue)
{
IntProp = intValue;
StringProp = stringValue;
}
// parameterless constructor: will be called on deserialization
// if exists and there is no special constructor
protected SerializableBase()
{
}
byte[] IBinarySerializable.Serialize(BinarySerializationOptions options)
{
MemoryStream ms = new MemoryStream();
using (BinaryWriter writer = new BinaryWriter(ms))
{
SerializeContent(writer);
}
return ms.ToArray();
}
void IBinarySerializable.Deserialize(BinarySerializationOptions options, byte[] serData)
{
using (BinaryReader reader = new BinaryReader(new MemoryStream(serData)))
{
DeserializeContent(reader);
}
}
protected virtual void SerializeContent(BinaryWriter writer)
{
writer.Write(currentVersionBase);
writer.Write(IntProp);
writer.Write(StringProp == null);
if (StringProp != null)
writer.Write(StringProp);
}
protected virtual void DeserializeContent(BinaryReader reader)
{
int version = reader.ReadInt32();
IntProp = reader.ReadInt32();
bool isStringPropNull = reader.ReadBoolean();
StringProp = isStringPropNull ? null : reader.ReadString();
// TODO: Read rest if version changes
}
}
public class SerializableDerived: SerializableBase
{
public bool BoolProp { get; set; }
// This property is new in this class (optional content)
public int NewIntProp { get; set; }
private static int currentVersionDerived = 2;
// this is the ordinary constructor
public SerializableDerived(int intValue, string stringValue, bool boolValue)
: base(intValue, stringValue)
{
BoolProp = boolValue;
}
// parameterless constructor: will be called on deserialization
// if exists and there is no special constructor
protected SerializableDerived()
: base()
{
}
protected override void SerializeContent(BinaryWriter writer)
{
base.SerializeContent(writer);
writer.Write(currentVersionDerived);
writer.Write(BoolProp);
writer.Write(NewIntProp);
}
protected override void DeserializeContent(BinaryReader reader)
{
base.DeserializeContent(reader);
int version = reader.ReadInt32();
BoolProp = reader.ReadBoolean();
if (version < 2)
return;
NewIntProp = reader.ReadInt32();
}
}
Of course the special constructor way can be used here, too.
Derived constructors should just call the base constructor, which should call DeserializeContent.
In that case FxCop and ReSharper may emit a warning that
virtual method is called from a constructor but that is alright here because this is a clean initialization pattern.
Deserialize |
Deserializes the inner state of the object from a byte array. Called only when the implementer does not have a constructor with (BinarySerializationOptions, byte[]) parameters.
Without such constructor parameterless constructor will be called if any (otherwise, no constructors will be executed). The special constructor should be used if the class has read-only fields to be restored.
|
Serialize |
Serializes the object into a byte array.
|