ScruffyDuck
ScruffyDuck

Reputation: 2666

What fields and properties should I serialize?

I do not think this is a duplicate. I have done some reading but did not find anything the same as this. It seems that fields can be serialized in binary formatters and in protobuf but not in XML. I don't know about JSON.

I am looking at replacing the standard .NET binary serializer with protobuf-net. The reason is to improve speed and get a smaller persisted file size.

In NET Binary I just marked the classes as serializable and left it at that. Not good I suspect.

With protobuf-net I need to specify what gets serialized with the [ProtoMember()] attribute. My newbie testing shows that private fields get serialized if so marked as do auto properties.

I do not want to change the class code definitions at all since I still need to be able to deserialize the old persisted data created by the NET serializer. I have a mixture of:

  1. Private fields that get used inside the class
  2. Private fields whose value gets set in constructors
  3. Private fields that are backing fields for non automatic properties
  4. Properties with the backing fields above
  5. Auto properties
  6. Properties with no setters that return some calculation or value determined internally

and probably some others. In other words pretty much every type of field and property.

I guess I need to persist any value that represents the state of the object that cannot be constructed after deserialization from the file.

I suppose there would be no harm in persisting every field and property but that would just make the job slower and the file bigger than it needs to be.

I think I can ignore private fields that are used only inside the class and are not set from outside. I think I should persist those fields that are set in constructors. I am not sure about backing fields - is it better to persist them or their public property? I must persist auto properties I can't persist properties with no setters so I need to persist whatever fields/properties get used in their calculations.

Am I on the right track or missing the point.

Thanks in advance.

Upvotes: 4

Views: 1942

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062660

We can't say what needs to be serialized. BinaryFormatter works on an "all fields" basis (unless they are explicitly marked not for serialization). You could use the same approach, but if you're using automatically implemented properties (which is fine) then note that you cannot add attributes to the backing field - unlike field-like events, the following is not valid c#:

[field:ProtoMember(1)] // not valid
public int X { get; set; }

This means that your only sensible choice is to decorate the property:

[ProtoMember(1)]
public int X { get; set; }

Because, if you change the automatically implemented property to a regular property, you will have broken BinaryFormatter's deserialization, since the field-name will have changed. That's fine, though - there's nothing wrong with marking either the fields or the properties (or both in the same type) for serialization. Another consideration on some platforms is accessibility: a private field may be inaccessible, where-as a public field works fine. And obviously public fields are pretty uncommon.

So:

  • decide what needs to be serialized (I can't tell you this)
  • mark it for serialization
  • do not change anything from automatically-implemented property to a regular property if you need BinaryFormatter to keep working (protobuf-net doesn't care if you change this)

Upvotes: 3

Related Questions