1
Vote

Private properties/fields in base classes will be not serialized

description

Hi,
i think I found a situation in which the serialization will not work properly.
To reconstruct my problem I will explain it:

I have an base class called TestBase attributed with the attribute [YAXSerializableType(FieldsToSerialize=YAXSerializationFields.AttributedFieldsOnly)].
This class has a private property Test from Type IList<T>, attributed with [YAXSerializableField].

When I serialize an instance of the class TestBase the property Test will be serialized.

Now I have a class TestDerived which derives from TestBase and is also attributed with the attribute [YAXSerializableType(FieldsToSerialize=YAXSerializationFields.AttributedFieldsOnly)].
This class has a private property Test2 from Type IList<T>, attributed with [YAXSerializableField].

When I serialize an instance of the class TestDerived the property Test2 will be serialized, but the
property Test from the base class not!

I've look at your source code and I think I have found the method which will not do all things right.

The place is in the method:
private IEnumerable<MemberWrapper> GetFieldsToBeSerialized(UdtWrapper typeWrapper)
of class YaxSerializer.

On the first line of the method the possible fields to be serialized will be retrieved by an call to:
typeWrapper.UnderlyingType.GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)

The problem is that the Type object returns only non public members of the class and will NOT return non public members of the base class.

To retrieve the non public members of the base class (if the serialized type has an base class) you should also call :
typeWrapper.UnderlyingType.BaseType.GetMembers(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)

I think the intersection of these calls are the complete set of possible fields to be serialized.

comments

sina_iravanian wrote May 15, 2014 at 2:35 PM

Hi,
It's a very tricky one, and can't be solved by that simplistic change.
First of all the inheritance depth is not always 2, it can be a lot. Apart from that reflection will not let the serialized private members be assigned to the child class instance. So deserialization will always require proper type-casts. Also the fields-to-serialize can be different in any class in the hierarchy. Grandfather may serialize all fields, father may serialize attributed fields only, and child may serialize public properties only.

This will not be a quick fix. It'll take me quite a few time to do that.

Meanwhile, I suggest changing your fields from private to protected, if it doesn't hurt your encapsulation.