2009-12-28 136 views
2

我有一個對象正在通過C#,.NET 3.5中的XmlSerializer進行序列化/反序列化。其中一個屬性(以及更多未來)是一個集合:列表,其中T是一個枚舉值。這個序列化/反序列化罰款。C#XML反序列化W /默認值

如果序列化版本沒有設置任何值,我們還使用「默認值」機制爲對象提供默認值。作爲一個簡單的例子,這裏是我們的冬:

public enum MyEnum { 
    Value1, 
    Value2 
} 

public class Foo 
{ 

    public List SomeSetting{ get; set; } 

    public Foo() 
    { 
    SomeSetting = new List(); 
    SomeSetting.Add(MyEnum.Value1); 
    SomeSetting.Add(MyEnum.Value2); 
    } 
} 

此代碼工作正常的對象被創建時設置SomeSetting的默認值。

但是,當我們對具有SomeSetting值的xml文件進行反序列化時,此默認值設置會導致問題:xml反序列化程序不會「重置」SomeSetting集合 - 它不會將其清除並填充新數據。相反,它增加了已經存在的數據。所以,如果xml文件將Value1序列化到它中,當我反序列化該文件時,我最終將SomeSettings的{Value1,Value2,Value1}存儲爲值。

我需要一種方法來進行xml反序列化處理,以便在xml文檔中沒有用於SomeSetting的數據時存在我的默認值,並且還可以在xml文檔中有數據時批量替換SomeSetting值。我怎樣才能做到這一點?

僅供參考 - 這不是文檔中的唯一屬性。該文件確實存在,並且正在爲其他「簡單」值進行序列化/反序列化。不過,這是造成問題的財產。我必須支持這種情況,因爲現在我需要做很多事情。

+0

我覺得IXmlSerializable接口會得到我我想要的......任何人有如何使用解決我的問題,這個接口有何建議? – 2009-12-28 17:05:06

+0

另一種選擇可能是,而不是分析自己 http://stackoverflow.com/questions/14768052/c-sharp-xml-deserialize-plus-design-suggestions – surya 2013-02-08 19:31:18

回答

1

僅供參考 - 我用IXMLSerializable接口解決了這個問題。請注意,這個代碼對於我在這個類中的需求非常具體,所以YMMV。



     public void WriteXml(XmlWriter writer) 
     { 
      foreach (PropertyInfo prop in GetType().GetProperties()) 
      { 
       XmlIgnoreAttribute attr; 
       if (prop.TryGetAttribute(out attr)) 
        continue; 

       if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(List))) 
       { 
        XmlSerializer serializer = new XmlSerializer(prop.PropertyType, new XmlRootAttribute(prop.Name)); 
        serializer.Serialize(writer, prop.GetValue(this, null)); 
       } 
       else 
       { 
        writer.WriteElementString(prop.Name, prop.GetValue(this, null).ToString()); 
       } 
      } 
     } 

     public void ReadXml(XmlReader reader) 
     { 
      if (reader.IsEmptyElement) 
       return; 

      XmlDocument xDoc = new XmlDocument(); 
      xDoc.Load(reader); 

      Type type = GetType(); 

      foreach (XmlNode node in xDoc.DocumentElement.ChildNodes) 
      { 
       PropertyInfo prop = type.GetProperty(node.Name); 
       if (prop != null && prop.CanWrite) 
       { 
        object value; 
        if (prop.PropertyType.IsEnum) 
        { 
         string stringValue = node.InnerText; 
         value = Enum.Parse(prop.PropertyType, stringValue); 
        } 
        else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition().Equals(typeof(List))) 
        { 
         Type enumType = prop.PropertyType.GetGenericArguments()[0]; 
         value = Activator.CreateInstance(prop.PropertyType); 
         var addMethod = value.GetType().GetMethod("Add"); 
         foreach (XmlNode subNode in node.ChildNodes) 
         { 
          object enumValue = Enum.Parse(enumType, subNode.InnerText); 
          addMethod.Invoke(value, new[] { enumValue }); 
         } 
        } 
        else 
        { 
         string stringValue = node.InnerText; 
         value = Convert.ChangeType(stringValue, prop.PropertyType); 
        } 
        prop.SetValue(this, value, null); 
       } 
      } 
     } 

     public XmlSchema GetSchema() 
     { 
      return null; 
     } 
0

快速和骯髒的是執行ISupportInitialize。所有的.NET串行器(IIRC)都尊重這個接口,並在反序列化之後調用EndInit

您可以在此處檢查集合的內容,並確定是否應該在當時添加默認值。我還建議檢查一下,看看你的實例在第一次使用之前是否已經初始化,如果沒有,就拋出異常。這將確保你的類的其他用戶知道你的實例在使用之前必須被初始化。

+0

似乎並沒有工作...方法從該接口不被xml序列化程序調用。 – 2009-12-28 15:30:53