c#中的XML序列化和DefaultValue("")相关问题

Mou*_*Mou 10 .net c# xml-serialization default-value

我的class属性有默认值,它将序列化.

public class DeclaredValue
{
    [XmlElement(ElementName = "Amount", DataType = "double", IsNullable = false), DefaultValue(999)]
    public double Amount { get; set; }

    [XmlElement(ElementName = "Reference2", DataType = "string", IsNullable = false), DefaultValue("")]
    public string Reference2 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

所以我们创建了DeclaredValue类的实例,并为Reference2属性提供了值,并且没有为Amount赋值.因此,当我们序列化DeclaredValue类时,在我的xml中找不到数量的标签.我提到金额"999"的默认值,然后为什么它不能在序列化中工作.我希望如果不为金额分配任何东西,那么amoun标签应该在我的xml中有默认值.

如果用户不为此属性分配任何内容,我需要以什么方式装饰它在序列化后始终在xml中带有默认值的amount属性.

请指导我在代码中需要更改的内容以获得我想要的输出.

Hen*_*man 17

根据MSDN上说明:

DefaultValueAttribute 不会导致使用属性的值自动初始化成员.您必须在代码中设置初始值.

有点令人惊讶的是,DefaultValue仅限制对象的写入,与其DefaultValue相等的成员将不会被写出.

您必须在加载自己之前或之后初始化成员,例如在构造函数中.

  • @ user728750,默认值是告诉序列化程序在保存xml文件时不将值写回.在序列化时,您可以使用它来保持配置清除默认值.使用默认值,如果当前值不是默认值,则序列化程序将仅写入流.这就是你使用它的原因 (5认同)
  • 只是为了确认,在这种情况下,在构造函数中设置所需的默认值对我有用. (4认同)
  • 您很可能需要构造函数来设置默认值. (2认同)

Maj*_*cRa 8

让我彻底描述正在发生的事情.

当调用XmlSerializer Deserialize()方法时,它使用默认构造函数创建一个新对象.我没有将任何DefaultValueAttributes应用于此对象,因为我们假设默认ctor应该"知道更好"如何默认初始化值.从这个角度来看 - 这是合乎逻辑的.

XmlSerializer不会序列化与DefaultValue属性标记的值相同的成员.从某些角度来看,这种行为也是由逻辑驱动的.

但是当你没有在ctor中初始化成员并调用deserialize方法时,XmlSerializer看不到相应的xml字段,但它看到字段/属性有DefaultValueAttribute,序列化器只留下这样的值(根据默认构造函数知道更好的假设如何初始化一个类"默认情况下").你得到了你的零.

解决方案 要通过这些DefaultValueAttributes初始化类成员(有时将初始化值放在适当的位置非常方便),您可以使用这样的简单方法:

    public YourConstructor()
    {
        LoadDefaults();
    }

    public void LoadDefaults()
    {
        //Iterate through properties
        foreach (var property in GetType().GetProperties())
        {
            //Iterate through attributes of this property
            foreach (Attribute attr in property.GetCustomAttributes(true))
            {   
                //does this property have [DefaultValueAttribute]?
                if (attr is DefaultValueAttribute) 
                {
                    //So lets try to load default value to the property
                    DefaultValueAttribute dv = (DefaultValueAttribute)attr;
                    try
                    {
                        //Is it an array?
                        if (property.PropertyType.IsArray)
                        {
                            //Use set value for arrays
                            property.SetValue(this, null, (object[])dv.Value); 
                        }
                        else
                        {
                            //Use set value for.. not arrays
                            property.SetValue(this, dv.Value, null);
                        }
                    }
                    catch (Exception ex)
                    {
                        //eat it... Or maybe Debug.Writeline(ex);
                    }
                }
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

这个"public void LoadDefaults()",可以作为对象的扩展进行装饰,或者用作辅助类的一些静态方法.