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

我的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类的实例并为Reference2属性提供了值,并且没有为Amount赋值。 因此,当我们序列化类DeclaredValue时,在我的xml中找不到数量的标签。 我提到金额“999”的默认值,然后为什么它不能在序列化中工作。 我希望如果不为金额分配任何东西,那么amoun标签应该在我的xml中有默认值。

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

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

根据MSDN上的说明 :

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

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

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

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

当调用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); } } } } } 

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

正如Henk Holterman所提到的,此属性不会自动设置默认值。 其目的主要是由可视化设计者用于将属性重置为其默认值。

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

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

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

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

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

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