C#XML反序列化W /默认值

问题描述:

我有一个对象正在通过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://*.com/questions/14768052/c-sharp-xml-deserialize-plus-design-suggestions – surya 2013-02-08 19:31:18

仅供参考 - 我用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; 
     } 

快速和肮脏的是执行ISupportInitialize。所有的.NET串行器(IIRC)都尊重这个接口,并在反序列化之后调用EndInit

您可以在此处检查集合的内容,并确定是否应该在当时添加默认值。我还建议检查一下,看看你的实例在第一次使用之前是否已经初始化,如果没有,就抛出异常。这将确保你的类的其他用户知道你的实例在使用之前必须被初始化。

+0

似乎并没有工作...方法从该接口不被xml序列化程序调用。 – 2009-12-28 15:30:53

另一个选择,而不是自己解析XML,我们可以使用我使用的方法。只是一个建议。

C# Xml Deserialize plus design suggestions