2014-03-31 25 views
1

我有一個類需要序列化。更改名稱空間後的DataContractSerializer兼容性

namespace serializedobject 
{ 
[DataContract] 
public class Class1 
{ 
    string string1_; 
    string string2_; 
    EntityA entity_; 

    [DataMember] 
    public string string3 
    { 
     get { return string1_; } 
     set { string1_ = value; } 
    } 

    [DataMember] 
    public string string2 
    { 
     get { return string2_; } 
     set { string2_ = value; } 
    } 
    [DataMember] 
    public EntityA Entity 
    { 
     get { return entity_; } 
     set { entity_ = value; } 
    } 

    public static Class1 FromXML(string desc) 
    { 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      StreamWriter writer = new StreamWriter(ms); 
      writer.Write(desc); 
      writer.Flush(); 

      ms.Seek(0, 0); 
      DataContractSerializer ser = new DataContractSerializer(typeof(Class1)); 
      return (Class1)ser.ReadObject(ms); 
     } 
    } 

    public string ToXML() 
    { 
     using (MemoryStream ms = new MemoryStream()) 
     { 
      DataContractSerializer ser = new DataContractSerializer(typeof(Class1)); 
      ser.WriteObject(ms, this); 
      ms.Seek(0, 0); 
      StreamReader reader = new StreamReader(ms); 
      return reader.ReadToEnd(); 
     } 
    } 
} 

[DataContract] 
public class EntityA 
{ 
    string name_; 
    [DataMember] 
    public string Name 
    { 
     get { return name_; } 
     set { name_ = value; } 
    } 
} 
} 

它與FromXML和ToXML一起工作正常。一個序列化方面,如:

<Class1 xmlns="http://schemas.datacontract.org/2004/07/serializedobject" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Entity><Name>az</Name></Entity><string2 i:nil="true"/><string3>test</string3></Class1> 

後來我需要一流的EntityA移動到另一個命名空間「外」,現在的系列化方面,如:

<Class1 xmlns="http://schemas.datacontract.org/2004/07/serializedobject" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Entity xmlns:a="http://schemas.datacontract.org/2004/07/outside"><a:Name>az</a:Name></Entity><string2 i:nil="true"/><string3>test</string3></Class1> 

但現在它改變命名空間之前創建的序列化的XML無法正確反序列化。我想這是因爲類「EntityA」改變了命名空間(xmlns:a added)。 有沒有人遇到過這個問題?任何建議?

+0

嘗試['[DataContract(Namespace =「」)]'](http://msdn.microsoft.com/zh-cn/library/system .runtime.serial ization.datacontractattribute.namespace%28v = vs.110%29.aspx)在這兩個版本的類。 –

+0

@MthetheWWatson,這也將是一個突破性的變化;我想你的意思是'Namespace =「http://schemas.datacontract.org/2004/07/serializedobject」' –

+0

@MarcGravell不,我的意思是「」 - 我只是要添加一個代碼示例。我在這裏假設他還沒有改變名稱空間 - 也就是說,他可以在保留任何數據之前進行此更改。如果不是,那麼我們必須將它應用到新班級。我也會將其添加到我的回覆中。 –

回答

2

可以通過指定來停止要添加到XML的名稱空間。這依賴於您在保存任何xml代碼之前設置該屬性。

只有當您尚未序列化任何數據時纔可以使用此方法,所以這是您在首次設計要序列化的類時要使用的方法。

(如果你已經得到了序列化,你必須處理的數據,看到我的回答如下的第二部分。)

此代碼示例有兩個班在兩個不同的命名空間,Test1Test2稱爲Demo

我們序列化使用的類從一個命名空間中的代碼,並使用來自其他命名空間中的類反序列化:

using System; 
using System.IO; 
using System.Runtime.Serialization; 
using System.Xml; 

namespace ConsoleApp1 
{ 
    namespace Test1 
    { 
     [DataContract(Namespace="")] 

     public sealed class Demo 
     { 
      [DataMember] 
      public string Value { get; set; } 
     } 
    } 

    namespace Test2 
    { 
     [DataContract(Namespace="")] 

     public sealed class Demo 
     { 
      [DataMember] 
      public string Value { get; set; } 
     } 
    } 

    sealed class Program 
    { 
     private void run() 
     { 
      string filename = Path.GetTempFileName(); 
      var demo1 = new Test1.Demo {Value = "DEMO"}; 
      ToFile(filename, demo1); 

      var demo2 = FromFile<Test2.Demo>(filename); 
      Console.WriteLine(demo2.Value); 
     } 

     public static void ToFile(string filename, object obj) 
     { 
      DataContractSerializer serializer = new DataContractSerializer(obj.GetType()); 

      using (var streamWriter = File.CreateText(filename)) 
      using (var xmlWriter = XmlWriter.Create(streamWriter, new XmlWriterSettings{Indent = true})) 
      { 
       serializer.WriteObject(xmlWriter, obj); 
      } 
     } 

     public static T FromFile<T>(string filename) 
     { 
      DataContractSerializer serializer = new DataContractSerializer(typeof(T)); 

      using (var textReader = File.OpenText(filename)) 
      using (var xmlReader = XmlReader.Create(textReader)) 
      { 
       return (T)serializer.ReadObject(xmlReader); 
      } 
     } 

     [STAThread] 
     static void Main(string[] args) 
     { 
      new Program().run(); 
     } 
    } 
} 

如果你有沒有Namespace=""屬性已經序列化的數據,那麼你會需要改爲將適當的命名空間應用於新類:

namespace Test1 
{ 
    [DataContract] 

    public sealed class Demo 
    { 
     [DataMember] 
     public string Value { get; set; } 
    } 
} 

namespace Test2 
{ 
    // Note the namespace includes both nested namespaces, i.e. ConsoleApp1.Test1 

    [DataContract(Namespace="http://schemas.datacontract.org/2004/07/ConsoleApp1.Test1")] 

    public sealed class Demo 
    { 
     [DataMember] 
     public string Value { get; set; } 
    } 
} 
+0

酷!它適用於我,非常感謝〜 – ArdenZhao

相關問題