其实我有这样的课程
[DataContract]
public class Item : IExtensibleDataObject
{
[Browsable(false)]
public virtual ExtensionDataObject ExtensionData { get; set; }
[DataMember]
public string ID { get; set; }
[DataMember]
public string Name { get; set; }
public Item()
: this(String.Empty, String.Empty)
{ }
public Item(string id, string name)
{
ID = id ?? String.Empty;
Name = name ?? String.Empty;
}
}
您可以轻松地序列化和反序列化它。但现在来了困难的部分:
我必须将属性Name
重命名为FullName
,并且每个新的xml序列化文件都应该出现FullName
,同时仍然可以读取旧文件。
将新属性名称输入新文件非常简单。只需重命名该属性即可。
为了兼容性,我会使用[DataMember(Name="Name")]
标记新的属性名称,但在这种情况下,如果我将此类写回文件,则会写入旧名称。
所以DataContract
中存在一些我可以将我的财产FullName
标记为两次的内容
[DataMember(Name="Name")]
[DataMember]
public string FullName { get; set}
还是有任何其他机制我怎么能证明两个值都可以写入这个,但只有一个会在写回来时出现?
我能想象的唯一方法是创建一个没有函数或类似东西的类LegacyItem
,但是会完成旧的DataContract
。另外还有一些隐式/显式运算符可以将LegacyItem
转换为Item
。最后但并非最不重要的是反序列化我必须做一些测试(可能只是一个简单的try/catch
)来找出我应该告诉DataContractSerializer
在文件中读取的类。
所以,即使这种方法可行,但对于这项任务来说听起来有点过于复杂,我想知道框架内是否还没有可以使这项任务更容易的东西。
答案 0 :(得分:3)
如果您不介意在您的课程中使用一些过时的代码(无论如何代码将少于您建议的整个第二课程),那么您可以这样做:
[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访问器序列化为FullName。序列化时,旧属性始终返回null,并且不会将事件发送到序列化XML。
此外,您可以将过时的属性标记为私有,以便在类外部不可见。
未来的一些提示,我更喜欢不为DataMember
属性使用自动属性。实际上,我通常将支持字段标记为DataMember
。最好始终为Name
属性包含可选的DataMember
参数。我承认我并不总是这样做,但这是一个很好的做法,因为如果你重构,那么你不会意外地违反合同 - >在Visual Studio中重命名属性或字段。
更新
OP Oliver本人提出了另一种解决方案......对于那些感兴趣的人来说,这就是这样。
[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;
}
}
}
答案 1 :(得分:0)
您应该查看IExtensibleDataObject
界面和相应的ExtensionDataObject
字段。它需要一些自定义代码才能使其正常运行,但有助于解决您的问题。