Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 序列化的DataContract向后兼容性_C#_.net_Serialization_Backwards Compatibility_Datacontract - Fatal编程技术网

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;
    }