2012-06-18 40 views
19

我有一個數據類,它與DataContractSerializer進行了序列化。該類使用[DataContract]屬性,沒有明確的Namespace聲明。因此,生成的xml文件中的命名空間是根據類的命名空間生成的。DataContractSerializer - 更改名稱空間並反序列化綁定到舊名稱空間的文件

類基本上是這樣的:

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

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

...和生成的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]屬性爲[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繼續並反序列化數據,即使命名空間不匹配。

+0

爲什麼要爲DataContract屬性中的名稱空間指定空字符串?你在做什麼獲得什麼? –

+2

我獲得的不是綁定到類的CLR名稱空間;這真的是這裏的問題。這個類正在改變它的CLR命名空間,我不想被綁定到那個實現細節。當然,我可以定義一個可以保持不變的xml命名空間值。但是對於這個實現,我看不到這樣做的好處,而不是簡單地刪除xml命名空間。這被用於簡單的文件序列化。 – harlam357

回答

15

一種可能的方法是將序列化程序使用的閱讀器封裝在將舊名稱空間映射到新名稱空間的閱讀器中,如下所示。很多代碼,但大多是微不足道的。

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); 
     } 
    } 
} 
+2

這工作得很好!我在錯誤的層面上攻擊了這個問題。非常感謝!我確實有一些更復雜的數據類型,它們包含'Dictionary '實例,這些實例證明有點難度。每個KVP的標籤都發生了變化,我假設基於名稱空間的變化,例如:到''。我必須對這些文件執行手動轉換,但沒關係。這些文件/類型代表了需要閱讀的少數內容。 – harlam357