[英]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.