Properly obsoleting old members in an XML Serializable class in C# VB .NET
Sometime ago I defined a class that was serialized using XML. That class contained a serializable property Alignment
of integer type. Now I have extended and updated this class, whereby a new property Position
was added, whose type is another class that also has several serializable properties. The new property Position
is now supposed to take on the role of old Alignment
property, that is since type of Position
property is another class, one of its members would contain the value that was previously contained in Alignment
property, thus making Alignment
prope开发者_StackOverflowrty obsolete.
What I am trying to figure out is how do I make sure that when I deserialize the old version of this class (without Position
property in it), I make sure that the deserializer would take the value of Alignment
property from the old class and set it as a value of one of the members of Position
property in the new class?
Private WithEvents _Position As Position = New Position(Alignment.MiddleMiddle, 0, True, 0, True)
Public Property Position() As Position 'NEW composite property that holds the value of the obsolted property, i.e. Alignment
Get
Return _Position
End Get
Set(ByVal value As Position)
_Position = value
End Set
End Property
Private _Alignment As Alignment = Alignment.MiddleMiddle
<Xml.Serialization.XmlIgnore(), Obsolete("Use Position property instead.")> _
Public Property Alignment() As Alignment 'The old, obsoleted property that I guess must be left for compliance with deserializing the old version of this class
Get
Return _Alignment
End Get
Set(ByVal value As Alignment)
_Alignment = value
End Set
End Property
Sorry the code is in VB, but it applies equally well to C# and any other .NET language.
Can you help me, please?
You can use the XMLSerializer events to help you out:
http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer_events.aspx
The code would look like:
XmlSerializer xs = new XmlSerializer(typeof(MyClass));
xs.UnknownAttribute += new XmlAttributeEventHandler(xs_UnknownAttribute);
xs.UnknownElement += new XmlElementEventHandler(xs_UnknownElement);
xs.UnknownNode += new XmlNodeEventHandler(xs_UnknownNode);
xs.UnreferencedObject +=
new UnreferencedObjectEventHandler(xs_UnreferencedObject);
Each event has the appropriate event args with very detailed information on the node/attrib/element in question, so more than enough for you to determine what to do.
If your class implements IXmlSerializable you can achieve what you want since you will now have total control on how your class is serialized and deserialized. This will allow you to handle objects serialized before the new Position
property, however, implementing IXmlSerializable
is a PITA because it's an all or nothing approach.
You can keep the Alignment property around and have it act as an alias to the Position property. If you mark it with [ObsoleteAttribute]
, this will warn users of your class that the property is obsolete and should no longer be used. At some point, you might be able to drop support for the obsolete property entirely. This resolves both serialization and public interface compatibility concerns.
精彩评论