如果你不介意在你的类中有一些过时的代码(无论如何,这比你建议的整个第二类的代码要少),那么你可以这样做:
[DataContract]
public class Item : IExtensibleDataObject
{
public virtual ExtensionDataObject ExtensionData { get; set; }
[DataMember]
public string ID { get; set; }
[DataMember(Name = "Name", EmitDefaultValue = false)]
private string _obsoleteName { get { return null; } set { if(value != null) FullName = value; } }
[DataMember]
public string FullName {get; set;}
public Item()
: this(String.Empty, String.Empty)
{ }
public Item(string id, string name)
{
ID = id ?? String.Empty;
FullName = name ?? String.Empty;
}
}
可以读取旧的XML,反序列化时将正确分配给新属性。然后在序列化时,只有新属性将通过set访问器序列化为全名。序列化时,旧属性始终返回空值,而不是向序列化XML发出的事件。
此外,还可以将过时属性标记为私有属性,以便在类外部不可见。
接下来有几个提示,我不喜欢使用自动属性
DataMember
性质。事实上,我通常将支持字段标记为
数据仓库
. 最好总是包括可选的
Name
的参数
数据仓库
属性。我承认,我自己并不总是这样做,但这是一个很好的实践,因为这样一来,如果重构--重命名Visual Studio中的属性或字段,就不会意外地破坏合同。
更新
奥立弗亲手提出了另一个解决办法…这是那些感兴趣的人的样子。
[DataContract]
public class Item : IExtensibleDataObject
{
public virtual ExtensionDataObject ExtensionData { get; set; }
[DataMember]
public string ID { get; set; }
[DataMember(Name = "Name", EmitDefaultValue = false)]
private string _obsoleteName;
[DataMember]
public string FullName {get; set;}
public Item()
: this(String.Empty, String.Empty)
{ }
public Item(string id, string name)
{
ID = id ?? String.Empty;
FullName = name ?? String.Empty;
}
[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
if(_obsoleteName != null && FullName == null)
{
//upgrade old serialized object to new version
//by copying serialized Name field to newer FullName
FullName = _obsoleteName;
//set _obsoleteName to null so that it stops serializing
_obsoleteName = null;
}
}
}