繁体   English   中英

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

[英]XML serialization and DefaultValue(“”) related problem in c#

我的 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; }
}

所以我们创建 DeclaredValue class 的实例,并为 Reference2 属性提供值,并且不为 Amount 分配任何内容。 因此,当我们序列化 class DeclaredValue 时,在我的 xml 中找不到金额标签。 我提到金额“999”的默认值,然后为什么它在序列化中不起作用。 我希望如果不为金额分配任何内容,那么我的 xml 中应该有 amoun 标签,默认值。

要做到这一点,如果用户没有为该属性分配任何内容,我需要以什么方式装饰它在序列化后总是在 xml 中带有默认值的数量属性。

请指导我需要更改代码以获得所需的 output。

根据MSDN 上的注释

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

有点令人惊讶的是,DefaultValue 只规定了 object 的写入,与其 DefaultValue 相等的成员不会被写出。

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

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

当调用 XmlSerializer Deserialize() 方法时,它使用默认构造函数创建一个新的 object。 我相信它不会对这个 object 应用任何 DefaultValueAttributes,因为假设默认 ctor 应该“更好地知道”如何在默认情况下初始化值。 从这个角度来看 - 这是合乎逻辑的。

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

但是当你不初始化ctor中的成员并调用deserialize方法时,XmlSerializer看不到对应的xml字段,但它看到该字段/属性有DefaultValueAttribute,序列化器只是留下这样的值(根据假设默认构造函数更好地知道如何“默认情况下”初始化 class)。 你有你的零。

解决方案要通过这些 DefaultValueAttributes 初始化 class 成员(有时将这些初始化值就位非常方便),您可以使用以下简单方法:

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

这个“public void LoadDefaults()”可以修饰为 object 的扩展或用作辅助 class 的某些 static 方法。

正如 Henk Holterman 提到的,此属性不会自动设置默认值。 它的目的主要是供视觉设计师用来将属性重置为其默认值。

正如其他人提到的, DefaultValue属性不会初始化属性。 您可以使用一个简单的循环来设置所有属性:

foreach (var property in GetType().GetProperties())
    property.SetValue(this, ((DefaultValueAttribute)Attribute.GetCustomAttribute(
        property, typeof(DefaultValueAttribute)))?.Value, null);

即使?.Value可以返回null ,它也适用于不可为空的类型,我对此进行了测试。

如果只有少数属性具有默认值,那么您应该只设置该值(如果存在)。

如果所有属性都应具有默认值,请删除? 如果你忘记了一个错误。

最有可能的是,arrays 不起作用,请参阅 MajesticRa 的解决方案如何处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM