2012-10-24 59 views
4

我試圖從xml文件反序列化一些設置。有問題的財產/基礎領域是一個叫AlertColors。我將基礎字段初始化爲白色,黃色和紅色,以確保此類的新實例具有有效的顏色設置。但是,當我反序列化時,_colorArgb結束了六個值,前三個是初始化值,最後三個是從xml文件中讀取的值。但屬性AlertColors不附加到該字段,但更改其元素。爲什麼我最終選擇了六種顏色的領域?Xml反序列化附加到列表

下面的代碼:

private List<int> _colorArgb = new List<int>(new int[] { Color.White.ToArgb(), Color.Yellow.ToArgb(), Color.Red.ToArgb() }); 

    public List<int> AlertColors 
    { 
     get 
     { 
      return _colorArgb; 
     } 

     set 
     { 
      for (int i = 0; i < Math.Min(_colorArgb.Count, value.Count); i++) 
      { 
       if (_colorArgb[i] != value[i]) 
       { 
        HasChanged = true; 
       } 
      } 

      _colorArgb = value; 
     } 
    } 

    public bool Deserialize(string filePath) 
    { 
     if (!File.Exists(filePath)) 
     { 
      Logger.Log("Error while loading the settings. File does not exist."); 

      return false; 
     } 

     FileStream fileStream = null; 

     try 
     { 
      fileStream = new FileStream(filePath, FileMode.Open); 
      System.Xml.Serialization.XmlSerializerFactory xmlSerializerFactory = 
       new XmlSerializerFactory(); 
      System.Xml.Serialization.XmlSerializer xmlSerializer = 
       xmlSerializerFactory.CreateSerializer(typeof(Settings)); 

      Settings deserializedSettings = (Settings)xmlSerializer.Deserialize(fileStream); 

      GetSettings(deserializedSettings); 

      Logger.Log("Settings have been loaded successfully from the file " + filePath); 
     } 
     catch (IOException iOException) 
     { 
      Logger.Log("Error while loading the settings. " + iOException.Message); 

      return false; 
     } 
     catch (ArgumentException argumentException) 
     { 
      Logger.Log("Error while loading the settings. " + argumentException.Message); 

      return false; 
     } 
     catch (InvalidOperationException invalidOperationException) 
     { 
      Logger.Log("Error while loading the settings. Settings file is not supported." + 
       invalidOperationException.Message); 

      return false; 
     } 
     finally 
     { 
      if (fileStream != null) 
       fileStream.Close(); 

      FilePath = filePath; 
     } 

     return true; 
    } 

    protected void GetSettings(Settings settings) 
    { 
     AlertColors = settings.AlertColors; 
    } 

而且說我反序列化XML文件的相關部分:

<AlertColors> 
    <int>-1</int> 
    <int>-15</int> 
    <int>-65536</int> 
    </AlertColors> 
+0

就像一邊:當你的當前值是{白色,白色,藍色}時,你會意識到改變檢測的迭代會錯過例如設置{白色,白色}? – Anton

+0

是的,我在想,如果有兩個值,它是前兩個值。用戶不應該手動改變它們。 – hattenn

+0

相關:http://stackoverflow.com/q/4217139/161052 – JYelton

回答

4

基本上,這只是如何XmlSerializer作品。除非列表是null,否則它絕不會嘗試設置一個值。特別是,時間,分項列出不具備二傳手 - 他們喜歡的東西:

private readonly List<Child> children = new List<Child>(); 
public List<Child> Children { get { return children; } } 

(因爲大多數人不希望外部調用者重新分配的名單;他們只是想讓他們改變內容)。

正因爲如此,XmlSerializer操作基本上像(過簡化):

var list = yourObj.SomeList; 
foreach({suitable child found in the data}) 
    list.Add({new item}); 

一個解決方法是使用一個數組,而不是一個列表;它總是希望分配一個數組回對象,所以對於一個陣列,其被實施更像(過簡化):

var list = new List<SomeType>(); 
foreach({suitable child found in the data}) 
    list.Add({new item}); 
yourObj.SomeList = list.ToArray(); 

然而,對於一個固定數目的值的,更簡單的實現可能只是:

public Foo Value1 {get;set;} 
public Foo Value2 {get;set;} 
public Foo Value3 {get;set;} 

(如果你明白我的意思)

+0

但它不會序列化/反序列化專用'_colorArgb'字段。它如何假設我將該字段用於屬性「AlertColors」並追加到它? – hattenn

2

要得到你想要的結果,而無需更改數據類型,你可以使用的DataContractSerializer(使用System.Runtime.Serialization;),而不是正常的XmlSerializer。它不調用默認構造你會因此結束了3種顏色,而不是6

var ser = new DataContractSerializer(typeof(Settings)); 
var reader = new FileStream(@"c:\SettingsFile.xml", FileMode.Open); 
var deserializedSettings = (Settings)ser.ReadObject(reader); 
1

即將有點遲到了,但我只是碰到了這個問題爲好。

接受的答案提到每次發生反序列化時都會分配數組。這非常有幫助。但我需要一個解決方案,不需要我改變屬性的類型並重寫一百萬行代碼。所以我想出了這個:

使用XML序列化器屬性,您可以將序列化器「重定向到」一個包裝原始屬性的數組。

[XmlIgnore] 
public List<int> AlertColors { get; set; } = new List<int>() { Color.White.ToArgb(), Color.Yellow.ToArgb(), Color.Red.ToArgb() }); 

[XmlArray(ElementName = "AlertColors")] 
public long[] Dummy 
{ 
     get 
     { 
      return AlertColors.ToArray(); 
     } 
     set 
     { 
      if(value != null && value.Length > 0) AlertColors = new List<int>(value); 
     } 
} 

Dummy屬性必須公開才能讓序列化程序訪問它。對我而言,這是一個小的代價,使原來的屬性保持不變,所以我不必修改任何附加代碼。