DataContractSerializer - 更改命名空间并反序列化绑定到旧命名空间的文件

har*_*357 20 .net c# datacontractserializer

我有一个序列化的数据类DataContractSerializer.该类使用[DataContract]没有显式Namespace声明的属性.因此,生成的xml文件中的命名空间是基于类的命名空间生成的.

该课程基本上如下:

namespace XYZ
{
   [DataContract]
   public class Data
   {
      [DataMember(Order = 1)]
      public string Prop1 { get; set; }

      [DataMember(Order = 2)]
      public int Prop2 { get; set; }
   }
}
Run Code Online (Sandbox Code Playgroud)

...以及生成的xml:

<?xml version="1.0" encoding="utf-8"?>
<Data xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/XYZ">
   <Prop1>StringValue</Prop1>
   <Prop2>11</Prop2>
</Data>
Run Code Online (Sandbox Code Playgroud)

现在我想通过将[DataContract]属性更改为更改类的名称空间(实际上将其删除)[DataContract(Namespace = "")].但是,一旦我执行此操作,之前使用原始命名空间序列化的文件不再反序列化.我收到以下异常:

Error in line 1 position XXX. Expecting element 'Data' from namespace ''.. Encountered 'Element' with name 'Data', namespace 'http://schemas.datacontract.org/2004/07/XYZ'.

这很有道理.我更改了命名空间.我很好.但是,似乎必须有一种方法可以告诉它DataContractSerializer继续并反序列化该数据,即使名称空间不匹配.

car*_*ira 17

一种可能的方法是将序列化程序使用的阅读器包装在将旧名称空间映射到新名称空间的阅读器中,如下所示.很多代码,但大多是微不足道的.

public class StackOverflow_11092274
{
    const string XML = @"<?xml version=""1.0"" encoding=""utf-8""?> 
<Data xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.datacontract.org/2004/07/XYZ""> 
   <Prop1>StringValue</Prop1> 
   <Prop2>11</Prop2> 
</Data>";

    [DataContract(Name = "Data", Namespace = "")]
    public class Data
    {
        [DataMember(Order = 1)]
        public string Prop1 { get; set; }

        [DataMember(Order = 2)]
        public int Prop2 { get; set; }
    }

    public class MyReader : XmlReader
    {
        XmlReader inner;
        public MyReader(XmlReader inner)
        {
            this.inner = inner;
        }

        public override int AttributeCount
        {
            get { return inner.AttributeCount; }
        }

        public override string BaseURI
        {
            get { return inner.BaseURI; }
        }

        public override void Close()
        {
            inner.Close();
        }

        public override int Depth
        {
            get { return inner.Depth; }
        }

        public override bool EOF
        {
            get { return inner.EOF; }
        }

        public override string GetAttribute(int i)
        {
            return inner.GetAttribute(i);
        }

        public override string GetAttribute(string name, string namespaceURI)
        {
            return inner.GetAttribute(name, namespaceURI);
        }

        public override string GetAttribute(string name)
        {
            return inner.GetAttribute(name);
        }

        public override bool IsEmptyElement
        {
            get { return inner.IsEmptyElement; }
        }

        public override string LocalName
        {
            get { return inner.LocalName; }
        }

        public override string LookupNamespace(string prefix)
        {
            return inner.LookupNamespace(prefix);
        }

        public override bool MoveToAttribute(string name, string ns)
        {
            return inner.MoveToAttribute(name, ns);
        }

        public override bool MoveToAttribute(string name)
        {
            return inner.MoveToAttribute(name);
        }

        public override bool MoveToElement()
        {
            return inner.MoveToElement();
        }

        public override bool MoveToFirstAttribute()
        {
            return inner.MoveToFirstAttribute();
        }

        public override bool MoveToNextAttribute()
        {
            return inner.MoveToNextAttribute();
        }

        public override XmlNameTable NameTable
        {
            get { return inner.NameTable; }
        }

        public override string NamespaceURI
        {
            get
            {
                if (inner.NamespaceURI == "http://schemas.datacontract.org/2004/07/XYZ")
                {
                    return "";
                }
                else
                {
                    return inner.NamespaceURI;
                }
            }
        }

        public override XmlNodeType NodeType
        {
            get { return inner.NodeType; }
        }

        public override string Prefix
        {
            get { return inner.Prefix; }
        }

        public override bool Read()
        {
            return inner.Read();
        }

        public override bool ReadAttributeValue()
        {
            return inner.ReadAttributeValue();
        }

        public override ReadState ReadState
        {
            get { return inner.ReadState; }
        }

        public override void ResolveEntity()
        {
            inner.ResolveEntity();
        }

        public override string Value
        {
            get { return inner.Value; }
        }
    }

    public static void Test()
    {
        DataContractSerializer dcs = new DataContractSerializer(typeof(Data));
        MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(XML));
        try
        {
            XmlReader r = XmlReader.Create(ms);
            XmlReader my = new MyReader(r);
            Data d = (Data)dcs.ReadObject(my);
            Console.WriteLine("Data[Prop1={0},Prop2={1}]", d.Prop1, d.Prop2);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这很棒!我在错误的级别攻击问题.非常感谢!我确实有一些更复杂的数据类型,包含`Dictionary <TKey,TValue>`实例,事实证明有点困难.每个KVP的标签都发生了变化,我假设它基于命名空间的变化,如下所示:`<d2p1:KeyValueOfintDataLg3n2mfJ>`到`<d2p1:KeyValueOfintDataLjh4bohd>`.我不得不对这些文件进行手动转换,但没关系.这些文件/类型代表了需要阅读的少数内容. (2认同)