C# 序列化的DataContract向后兼容性
我上过这样的课:C# 序列化的DataContract向后兼容性,c#,.net,serialization,backwards-compatibility,datacontract,C#,.net,Serialization,Backwards Compatibility,Datacontract,我上过这样的课: [DataContract(Namespace = "blah")] public class Item { [DataMember(Order = 0)] public int Index { get; set; } [DataMember(Order = 1)] public Uri ItemSource { get; set; } [DataMember(Order = 2)] public Uri ErrorSourc
[DataContract(Namespace = "blah")]
public class Item
{
[DataMember(Order = 0)]
public int Index { get; set; }
[DataMember(Order = 1)]
public Uri ItemSource { get; set; }
[DataMember(Order = 2)]
public Uri ErrorSource { get; set; }
}
我有很多它的序列化副本(在文件中)(包括一些生产文件),
现在我的任务是将该类更改为以下内容:
[DataContract(Namespace = "blah")]
public class Item
{
[DataMember(Order = 0)]
public int Index { get; set; }
[DataMember(Order = 1)]
public ItemSourcesCollection Sources { get; set; }
}
ItemSourcesCollection所在的位置
[CollectionDataContract(ItemName = "ItemSourceItem", Namespace = "blah")]
public class ItemSourcesCollection : List<ItemSource> {}
其中ItemSourceType是
[Serializable]
public enum ItemSourceType
{
Data,
Errors
}
问题在于向后兼容性。旧的序列化项是否可以正确反序列化?向后兼容迁移数据契约的最佳实践/模式是什么?是的,经过一些反思,这是可能的。我在反序列化过程中手动检查以前的版本 第一次使用物品类别:
[DataContract(Namespace = "blah")]
public class Item : IExtensibleDataObject
{
[DataMember(Order = 0)]
public int Index { get; set; }
[DataMember(Order = 1)]
public ItemSourcesCollection Sources { get; set; }
}
现在,反序列化方法的棘手问题是:
/// <summary>
/// The deserialized.
/// </summary>
/// <param name="context">
/// The streaming context.
/// </param>
[OnDeserialized]
private void Deserialized(StreamingContext context)
{
// reflection for backward compatibilty only
if (this.ExtensionData == null)
{
return;
}
IList members = this.CheckForExtensionDataMembers();
if (members == null)
{
return;
}
string value = this.GetExtensionDataMemberValue(members, "ItemSource");
// do something with value
value = this.GetExtensionDataMemberValue(members, "ErrorSource");
// do something with value
}
/// <summary>
/// The check for extension data members.
/// </summary>
/// <returns>
/// Thel list of extension data memebers.
/// </returns>
private IList CheckForExtensionDataMembers()
{
PropertyInfo membersProperty = typeof(ExtensionDataObject).GetProperty(
"Members", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
var members = (IList)membersProperty.GetValue(this.ExtensionData, null);
if (members == null || members.Count <= 0)
{
return null;
}
return members;
}
/// <summary>
/// The get extension data member value.
/// </summary>
/// <param name="members">
/// The members.
/// </param>
/// <param name="dataMemberName">
/// The data member name.
/// </param>
/// <returns>
/// Returns extension data member value.
/// </returns>
private string GetExtensionDataMemberValue(IList members, string dataMemberName)
{
string innerValue = null;
object member =
members.Cast<object>().FirstOrDefault(
m =>
((string)m.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).GetValue(m, null)).Equals(
dataMemberName, StringComparison.InvariantCultureIgnoreCase));
if (member != null)
{
PropertyInfo valueProperty = member.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
object value = valueProperty.GetValue(member, null);
PropertyInfo innerValueProperty = value.GetType().GetProperty("Value", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Public);
object tmp = innerValueProperty.GetValue(value, null);
var s = tmp as string;
if (s != null)
{
innerValue = s;
}
}
return innerValue;
}
//
///数据被反序列化。
///
///
///流式处理上下文。
///
[已序列化]
私有void反序列化(StreamingContext上下文)
{
//仅针对向后兼容性的反射
if(this.ExtensionData==null)
{
返回;
}
IList members=this.CheckForExtensionDataMembers();
如果(成员==null)
{
返回;
}
字符串值=this.GetExtensionDataMemberValue(成员,“ItemSource”);
//做有价值的事
value=this.GetExtensionDataMemberValue(成员,“ErrorSource”);
//做有价值的事
}
///
///检查扩展数据成员。
///
///
///扩展数据成员的列表。
///
私有IList CheckForExtensionDataMembers()
{
PropertyInfo membersProperty=typeof(ExtensionDataObject).GetProperty(
“成员”,BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
var members=(IList)membersProperty.GetValue(this.ExtensionData,null);
if(members==null | | members.Count
((字符串)m.GetType().GetProperty(“名称”,BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).GetValue(m,null)).Equals(
dataMemberName,StringComparison.InvariantCultureIgnoreCase);
如果(成员!=null)
{
PropertyInfo valueProperty=member.GetType().GetProperty(“Value”,BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
对象值=valueProperty.GetValue(成员,null);
PropertyInfo innerValueProperty=value.GetType().GetProperty(“value”,BindingFlags.Public | BindingFlags.Instance | BindingFlags.Public);
对象tmp=innerValueProperty.GetValue(值,null);
var s=作为字符串的tmp;
如果(s!=null)
{
innerValue=s;
}
}
返回内部值;
}
以上所有内容都将放在项目中。非常感谢,我将尝试您的方法并在这里发布我的结果。
/// <summary>
/// The deserialized.
/// </summary>
/// <param name="context">
/// The streaming context.
/// </param>
[OnDeserialized]
private void Deserialized(StreamingContext context)
{
// reflection for backward compatibilty only
if (this.ExtensionData == null)
{
return;
}
IList members = this.CheckForExtensionDataMembers();
if (members == null)
{
return;
}
string value = this.GetExtensionDataMemberValue(members, "ItemSource");
// do something with value
value = this.GetExtensionDataMemberValue(members, "ErrorSource");
// do something with value
}
/// <summary>
/// The check for extension data members.
/// </summary>
/// <returns>
/// Thel list of extension data memebers.
/// </returns>
private IList CheckForExtensionDataMembers()
{
PropertyInfo membersProperty = typeof(ExtensionDataObject).GetProperty(
"Members", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
var members = (IList)membersProperty.GetValue(this.ExtensionData, null);
if (members == null || members.Count <= 0)
{
return null;
}
return members;
}
/// <summary>
/// The get extension data member value.
/// </summary>
/// <param name="members">
/// The members.
/// </param>
/// <param name="dataMemberName">
/// The data member name.
/// </param>
/// <returns>
/// Returns extension data member value.
/// </returns>
private string GetExtensionDataMemberValue(IList members, string dataMemberName)
{
string innerValue = null;
object member =
members.Cast<object>().FirstOrDefault(
m =>
((string)m.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).GetValue(m, null)).Equals(
dataMemberName, StringComparison.InvariantCultureIgnoreCase));
if (member != null)
{
PropertyInfo valueProperty = member.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
object value = valueProperty.GetValue(member, null);
PropertyInfo innerValueProperty = value.GetType().GetProperty("Value", BindingFlags.Public | BindingFlags.Instance | BindingFlags.Public);
object tmp = innerValueProperty.GetValue(value, null);
var s = tmp as string;
if (s != null)
{
innerValue = s;
}
}
return innerValue;
}