Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The protobuf-net library is a contract-based serializer for .NET that uses the binary Protocol Buffers serialization format. The API follows typical .NET patterns and is broadly comparable to XmlSerializer and DataContractSerializer.
Some behaviors and features of protobuf-net will be notable during migrations from BinaryFormatter, and many scenarios require applying attributes to members.
- By default, both public and non-public types are serializable, with the serializer expecting a parameterless constructor.
- protobuf-net requires each serializable type to be annotated with
[ProtoContract]attribute; this attribute can optionally specify theSkipConstructor = trueproperty, which removes the need for any particular constructor. - Every serializable non-static field and a property needs to be annotated with
[ProtoMember(int identifier)]attribute. The member names aren't encoded in the data. Instead, the users must pick a positive integer to identify each member which must be unique within that type. - Inheritance must be explicitly declared via
[ProtoInclude(...)]attribute on each type with known subtypes. - Read-only fields are supported by default.
- Alternatively, some non-attributed tuple-like types are recognized by constructor pattern; a type with a constructor that has parameters that match (by name) all of the declared public members will be interpreted as a tuple, and the parameter order will be used to infer the identifier for that member.
- The use of the
protobuf-net.BuildToolsdesign-time package is highly recommended; this offers compile-time warnings of common errors.
Step by step migration
- Find all the usages of
BinaryFormatter. - Ensure that the serialization code paths are covered with tests, so you can verify your changes and avoid introducing bugs.
- Install
protobuf-netpackage (and optionallyprotobuf-net.BuildTools). - Find all the types that are being serialized with
BinaryFormatter. - For types that you can modify:
- Annotate with
[ProtoContract]attribute all types that are marked with[Serializable]or implement theISerializableinterface. If these types are not exposed to other apps (example: you are writing a library) that may use different serializers likeDataContractSerializer, you can remove the[Serializable]andISerializableannotations. - For derived types, apply
[ProtoInclude(...)]to their base types (see the example below). - For every type that declares any constructor that accepts parameters, add a parameterless constructor, or specify
SkipConstructor = trueon the[ProtoContract]attribute. Leave a comment that explains the protobuf-net requirement (so nobody removes it by accident). - Mark all the members (fields and properties) that you wish to serialize with
[ProtoMember(int identifier)]. All identifiers must be unique within a single type, but the same numbers can be re-used in sub-types if inheritance is enabled.
- Annotate with
- For types that you can't modify:
- For types provided by the .NET itself, you can use
ProtoBuf.Meta.RuntimeTypeModel.Default.CanSerialize(Type type)API to check if they are natively supported by protobuf-net. - You can create dedicated data transfer objects (DTO) and map them accordingly (you could use implicit cast operator for that).
- Use the
RuntimeTypeModelAPI to define everything that the attributes allow for.
- For types provided by the .NET itself, you can use
- Replace the usage of
BinaryFormatterwithProtoBuf.Serializer.
-[Serializable]
+[ProtoContract]
+[ProtoInclude(2, typeof(Point2D))]
public class Point1D
{
+ [ProtoMember(1)]
public int X { get; set; }
}
-[Serializable]
+[ProtoContract]
public class Point2D : Point1D
{
+ [ProtoMember(2)]
public int Y { get; set; }
}