2012-10-24 2 views
4

XML 파일에서 일부 설정을 deserialize하려고합니다. 문제가되는 속성/기본 필드는 AlertColors입니다. 기본 필드를 흰색, 노란색 및 빨간색으로 초기화하여이 클래스의 새 인스턴스에 유효한 색상 설정이 있는지 확인합니다. 하지만 deserialize 할 때 _colorArgb은 6 개의 값으로 끝나고, 처음 세 개는 초기화 값이고 마지막 세 개는 xml 파일에서 읽은 값입니다. 그러나 속성 AlertColors은 필드에 추가하지 않지만 요소를 변경합니다. 왜 내가 6 가지 색으로 된 들판을 가지고 있을까?Xml deserialization이 목록에 추가됩니다.

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(); 

그러나, 값의 고정 번호, 간단한 구현은 단지 수 있습니다 : 대신 일반 XmlSerializer를,

+0

그러나 그것은 개인'_colorArgb' 필드를 직렬화/비 직렬화하지 않습니다. 어떻게하면 AlertColors 속성에 해당 필드를 사용하고 있다고 가정하고 추가 할 것입니까? – hattenn

2

당신의 데이터 유형을 변경하지 않고 원하는 결과를 얻기 위해 (당신이 무슨 뜻인지 볼 경우)

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

, 당신은 (들은 System.Runtime.Serialization 사용) DataContractSerializer를 사용할 수 있습니다. 따라서 당신이 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 Serializer 속성을 사용하면 serializer를 원래 속성을 감싸는 배열로 '리디렉션'할 수 있습니다.

[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 속성은 serializer가 액세스 할 수 있도록 공개되어야합니다. 그러나 나에게 이것은 지불 할 작은 가격이었고 원래 속성은 변경되지 않았으므로 추가 코드를 수정할 필요가 없었습니다.

관련 문제