BinarySerializer
A declarative serialization framework for controlling formatting of data at the byte level. Jump to
docs for more info and a walkthrough.
Features
- Field lengths/offset
- Collections (implicit/explicit termination)
- Bindings
- Conditionals
- Subtypes
- Converters
- Enum Support (string or value)
- Member Streams
- MemberSerialized/MemberDeserialized events
- Member-level Big/Little Endian Support
- Non-seekable stream support
- IBinarySerializable
Attributes
| |
Bindable |
Non-seek Support |
| Ignore |
|
Yes |
| SerializeAs |
|
Yes |
| SerializeAsEnum |
|
Yes |
| FieldOffset |
Yes |
|
| FieldLength |
Yes |
Yes |
| FieldCount |
Yes |
Yes |
| Subtype |
Yes |
Yes |
| SerializeWhen |
Yes |
Yes |
| SerializeUntil |
Yes |
|
| ItemLength |
Yes |
Yes |
| ItemSerializeUntil |
Item Bindable |
Yes |
Example
public class Cereal
{
[SerializeAs(SerializedType.NullTerminatedString, Order=0)]
public string IsLittleEndian { get; set; }
[FieldLength(6)]
public string Name { get; set; }
[SerializeAs(SerializedType.NullTerminatedString, Order = 0)]
public string Manufacturer { get; set; }
public ushort OtherStuffCount { get; set; }
[FieldOffset(1000)]
public int Outlier { get; set; }
public NutritionalInformation NutritionalInformation { get; set; }
public double DoubleField;
[FieldCount("OtherStuffCount")]
[SerializeAs(SerializedType.SizedString)]
[ItemLength(3)]
public List<string> OtherStuff { get; set; }
[FieldLength(4)]
[SerializeAs(SerializedType.SizedString)]
public CerealShape Shape { get; set; }
public CerealShape DefinitelyNotTheShape { get; set; }
[SerializeWhen("Shape", CerealShape.Square)]
public string DontSerializeMe { get; set; }
[SerializeWhen("Shape", CerealShape.Circular)]
public string SerializeMe { get; set; }
[SerializeUntil((byte)0)]
public List<string> ExplicitlyTerminatedList { get; set; }
[FieldLength(9)]
public List<CerealShape> ImplicitlyTerminatedList { get; set; }
[FieldCount(3)]
public int[] ArrayOfInts { get; set; }
[FieldLength]
public string InvalidFieldLength { get; set; }
public long DisclaimerLength { get; set; }
[FieldLength("DisclaimerLength")]
public Stream Disclaimer { get; set; }
}
public class NutritionalInformation
{
public int Calories { get; set; }
public float Fat { get; set; }
public ushort Cholesterol { get; set; }
[SerializeAs(Order=1)]
public ushort VitaminA { get; set; }
[SerializeAs(Order=0)]
public uint VitaminB { get; set; }
[FieldCount("OtherStuffCount", Mode = RelativeSourceMode.FindAncestor, AncestorType = "Cereal")]
public List<string> OtherNestedStuff { get; set; }
[FieldCount("OtherStuffCount", Mode = RelativeSourceMode.FindAncestor, AncestorLevel = 2)]
public List<string> OtherNestedStuff2 { get; set; }
[ItemSerializeUntil("Last", true)]
public List<Toy> Toys { get; set; }
[FieldLength("Outlier", ConverterType = typeof(DoubleOutlierConverter), Mode = RelativeSourceMode.FindAncestor, AncestorLevel = 2)]
public string WeirdOutlierLengthedField { get; set; }
public Ingredients Ingredients { get; set; }
}
using (var stream = new FileStream("cereal.dat", FileMode.Open, FileAccess.Read))
{
var serializer = new BinarySerializer();
var entry = serializer.Deserialize<IsoDirectoryRecord>(stream);
}
Notes
This framework was developed largely to enable interoperability with legacy systems. While it could be used for data storage or hibernation, that was not the intention and there are likely better frameworks (and approaches, frankly) for that sort of
thing.
See the iso9660 project or the unit tests for example usages.