Question

In. Net you can mark a field as non serializable, and it will be skipped during serialization.

I'm looking for a simple method that will allow me to control in runtime whether a specific field should be serialized.

Was it helpful?

Solution

You are referring to "mark a field as non serializable", so I assume you are using BinaryFormatter and [NonSerialized]. If so, the only way to do conditional serialization is by implementing ISerializable and adding a similar constructor, and putting the logic in the GetObjectData implementation. This is tedious and error prone, though. I would suggest looking at protobuf-net, which has simpler conditional serialization, using the standard patterns used by TypeDescriptor and XmlSerializer, but is still binary output (more efficient than BinaryFormatter, actually). Specifically:

[ProtoContract]
public class SomeType {
    [ProtoMember(1)]
    public string Name {get;set;}

    private bool ShouldSerializeName() {
       // return true to serialize Name, false otherwise
    }
}

This ShouldSerialize* is a standard name-based convention - nothing specific to this serializer.

Here's the same via ISerializable:

[Serializable]
public class SomeType : ISerializable
{
    public SomeType() { }
    public string Name { get; set; }


    void ISerializable.GetObjectData(
             SerializationInfo info, StreamingContext context)
    {
        if (/* should serialize Name */) info.AddValue("Name", Name);
        //... all other fields
    }
    protected SomeType(SerializationInfo info, StreamingContext context)
    {
        foreach (SerializationEntry entry in info)
        {
            switch (entry.Name)
            {
                case "Name": Name = (string)entry.Value; break;
                //... all other fields
            }
        }
    }
}

Lots more to maintain; in particular, you have to take responsibility for all members when using ISerializable - however, if you just use protobuf-net you can handle each on a case-by-case basis.

Actually, you can mix-and-match too, i.e. if you are stuck with using BinaryFormatter, you can still offload the work to protobuf-net, but it will change the format (so won't be compatible with old data). For example:

[Serializable, ProtoContract]
public class SomeType : ISerializable
{
    public SomeType() { }
    [ProtoMember(1)]
    public string Name { get; set; }
    private bool ShouldSerializeName() { /* condition */ }

    void ISerializable.GetObjectData(
        SerializationInfo info, StreamingContext context)
    {
        Serializer.Serialize(info, this); 
    }
    protected SomeType(SerializationInfo info, StreamingContext context)
    {
        Serializer.Merge(info, this);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top