Handling XML Serialization of read-only fields in C#
I've got a class that has a read-only property defined that is actually a reference to a very mutable object, and I'm wondering what the best way to handle the serialization of it is.
For example:
public class classA {
public readonly classB B = new classB();
}
public class classB {
public string Name = "Test";
}
This can be serialized to (if it wasn't for the fact the 'B' field is readonly)
<classA>
<B>
<Name>Test</Name>
</B>
</classA>
but I can't deserialize it, as the serializer would attempt to create a new instance of classB, and set the field on classA to that new object.
If I make the property not read-only, this opens up the possibility of client code changing the instance of classB that's used, which isn't acceptable (many other objects will have sunk events on that instance, so it can't just be replaced like this). Alternatively, I could have the setter simply copy the values from the object given into the instance that's already there, but this seems excessively cumbersome just to accommodate the serializer.
I considered having a separate property with a setter to handle the serialization, and setting it to [Browsable(BrowsableState.Never)], but th开发者_StackOverflow中文版is still exposes the ability to change the instance to anyone who gets clever with reflection.
Is there a way of telling the serializer to populate the existing object on deserialization, or am I going to have to create a custom serializer?
Well, IXmlSerializable
is an option, but it is not a desirable one; it is pretty hard to write a robust implementation of anything non-trivial.
If having an immutable property is that important, then maybe consider having a separate DTO implementation - i.e. one set of simple, mutable classes for persistence, which you translate into your domain entities.
Alternatively, some other serializers may help; for example, DataContractSerializer
will work on private fields:
[DataContract]
public class classA {
[DataMember]
private classB b = new classB();
public classB B { get {return b; } }
}
Unfortunately, I can't see a way around using a custom XML serializer to address your situation. However, I believe binary serialization would work in this instance if that is an option.
精彩评论