MistyD
MistyD

Reputation: 17223

Ignore a property during serialization using BinaryFormatter only if its null

I am currently using BinaryFormatter for creating a stream. I am aware of the fact that I can mark a property with the attribute [field: NonSerialized] if I want it to be ignored by the BinaryFormatter during serialization. My question is if there is a way for me to specify that all null properties of a field should be ignored during Binary Serialization ? I am currently doing something like this to get the stream

       var formatter = new BinaryFormatter();
        using (var stream = new MemoryStream())
        {
            formatter.Serialize(stream, MyObjectinstance);
        }

Upvotes: 2

Views: 647

Answers (2)

Oguz Ozgul
Oguz Ozgul

Reputation: 7187

Not designed for this exact purpose, but the ISerializationSurrogate can help.

I will edit and enrich my answer later, but the following accomplishes what you need, but fails to achieve the same for the nested objects.

The obj parameter here is the instance of your class. We simply omit adding a field to the serialization info if its value is null:

public class NullFieldOmittingSurrogate : ISerializationSurrogate
{
    void ISerializationSurrogate.GetObjectData(object obj, SerializationInfo info, StreamingContext context)
    {
        if (obj != null)
        {
            foreach (FieldInfo field in obj.GetType().GetFields
                (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                object fieldValue = field.GetValue(obj);
                if (fieldValue != null)
                {
                    info.AddValue(field.Name, fieldValue);
                }
            }
        }
    }

    object ISerializationSurrogate.SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        // The deserialization works without the need for this surrogate
        throw new NotImplementedException();
    }
}

We need to pass this surrogate to our binary formatter, so here is a method which passes this and other required information to it:

public static void SerializeObject(object myObjectInstance, Stream destinationStream)
{
    SurrogateSelector surrogateSelector = new SurrogateSelector();
    surrogateSelector.AddSurrogate
    (
        myObjectInstance.GetType(),
        new StreamingContext(StreamingContextStates.All),
        new NullFieldOmittingSurrogate()
    );
    IFormatter serializer = new BinaryFormatter();
    serializer.SurrogateSelector = surrogateSelector;
    serializer.Serialize(destinationStream, myObjectInstance);
}

And finally, how to use: (SerClass is irrelevant and is a class having 4 properties all of type object, for unit testing)

public static void Main()
{
    MemoryStream memoryStream = new MemoryStream();
    SerializeObject
    (
        new SerClass()
        {
            Prop2 = 5,
            Prop4 = "ABCD",
            Nested = new SerClassNested() { Prop1 = 8, Prop3 = "EFGH" }
        },
        memoryStream
    );

    SerClass serClass = new BinaryFormatter().Deserialize(memoryStream) as SerClass;
}

Hope this helps. I am still working on the nested class type fields.

Upvotes: 3

Knodel12
Knodel12

Reputation: 41

What is your particular use case of excluding that from the serialization? Null won't take up hardly any space, and this won't improve deserialization or serialization performance. When deserializing you could also handle null differently as well, by having the OnDeserialized event handled.

Upvotes: 0

Related Questions