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
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);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个"public void LoadDefaults()",可以作为对象的扩展进行装饰,或者用作辅助类的一些静态方法.