具有默认值的C#XML反序列化 [英] C# XML Deserialization W/ Default Values

查看:144
本文介绍了具有默认值的C#XML反序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象正在通过C#.NET 3.5中的XmlSerializer进行序列化/反序列化。集合之一是属性(在将来还会增加):列表,其中T是枚举值。

I've got an object that is being serialized / deserialized via the XmlSerializer in C#, .NET 3.5. One of the properties (and more in the future) is a collection: List where T is an enum value. This serializes / deserializes fine.

我们还使用默认值机制为对象提供默认值,以防序列化版本没有任何值组。举一个简单的例子,这就是我们所要进行的操作:

We are also using a "default values" mechanism to provide default values for the object, in case the serialized version doesn't have any value set. as a simple example, here is what we are dong:

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的默认值在构造对象时。

This code works fine for setting the default values of SomeSetting when the object is constructed.

但是,当我们反序列化具有SomeSetting值的xml文件时,此默认值设置会导致问题:xml反序列化器不会重置 SomeSetting集合-它不会将其清除干净并填充新数据。而是将其添加到已经存在的数据中。因此,如果xml文件中已序列化了Value1,则当我反序列化该文件时,最终会得到SomeSettings,其中存储的值是{Value1,Value2,Value1}。

However, when we are deserializing an xml file that has values for SomeSetting, this default value setup is causing problems: the xml deserializer does not 'reset' the SomeSetting collection - it does not wipe it clean and populate with new data. Rather, it adds on to the data that is already there. So, if the xml file has Value1 serialized into it, when I deserialize that file, i end up with SomeSettings having {Value1, Value2, Value1} as the values being stored.

我需要xml反序列化过程的一种方法,以在xml文档中没有SomeSetting的数据时允许我的默认值存在,并且还需要在xml文档中有数据时批发替换SomeSetting值。我该怎么做?

I need a way for the xml deserialization process to allow my default values to exist when there is no data for SomeSetting in the xml document, and also to wholesale replace the SomeSetting values when there is data in the xml document. How can I do this?

仅供参考-这不是文档中唯一的属性。该文档确实存在,并且正在针对其他简单值进行序列化/反序列化。但是,这是导致问题的属性。我必须支持这种情况,因为我现在需要做很多事情。

FYI - this is not the only property in the document. The document does exist, and is being serialized / deserialized for the other 'simple' values. This is the property that is causing problems, though. I have to support this scenario because I need to do this a lot, now.

推荐答案

仅供参考-我使用IXMLSerializable解决了这个问题接口。请注意,这段代码非常适合我在这一堂课中的需要,所以YMMV。

FYI - i solved this with the IXMLSerializable interface. Note that this code is very specific to my needs in this one class, so 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;
        }

这篇关于具有默认值的C#XML反序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆