Microsoft XmlSerializer中似乎存在错误/不一致:如果您有一个标有System.ComponentModel.DefaultValue
属性的属性,则不会序列化。足够公平 - 这可以被视为预期的行为。
问题是反序列化时不遵守相同的属性。下面的代码说明了这个问题。
问题是我怎么能绕过这个?我有可能有数百个业务类在UI层(视图)中使用默认值,因此构造函数中的默认值初始化不是一个选项。它必须是通用的。我可以创建一个全新的默认属性,但它似乎是重复的工作。您是否看到了覆盖XmlSerializer行为的方法,还是应该使用另一个更好地完成工作的序列化程序?
示例代码:
public class DefaultValueTestClass
{
[System.ComponentModel.DefaultValue(10000)]
public int Foo { get; set; }
}
[TestMethod]
public void SimpleDefaultValueTest()
{
// Create object and set the property value TO THE DEFAULT
var before = new DefaultValueTestClass();
before.Foo = 10000;
// Serialize => xml
var serializer = new System.Xml.Serialization.XmlSerializer(typeof(DefaultValueTestClass));
string xml;
using (var stream = new System.IO.StringWriter())
{
serializer.Serialize(stream, before);
xml = stream.ToString();
}
// Deserialize the same object
DefaultValueTestClass after;
using (var reader = new System.IO.StringReader(xml))
{
after = (DefaultValueTestClass)serializer.Deserialize(reader);
}
// before.Foo = 10000
// after.Foo = 0
Assert.AreEqual(before.Foo, after.Foo);
}
答案 0 :(得分:0)
你的工作来实现默认值; [DefaultValue]
只是说“这是默认设置,您不必担心这个问题” - 它不会应用它。这不仅适用于XmlSerializer
,还适用于System.ComponentModel
所属的核心[DefaultValue]
API(驱动PropertyGrid
中的粗体/非粗体等)< / p>
基本上:
public class DefaultValueTestClass
{
public DefaultValueTestClass()
{
Foo = 10000;
}
[DefaultValue(10000)]
public int Foo { get; set; }
}
将以您期望的方式运作。如果您希望它序列化是否是特定值,那么正确的实现是:
public class DefaultValueTestClass
{
public DefaultValueTestClass()
{
Foo = 10000;
}
public int Foo { get; set; }
}
如果您想保留[DefaultValue]
,但希望它始终序列化,那么:
public class DefaultValueTestClass
{
[DefaultValue(10000)]
public int Foo { get; set; }
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeFoo() { return true; }
}
其中ShouldSerialize*
是System.ComponentModel
中可被多个序列化程序识别的另一种模式。
这里有一些用户界面代码,表明XmlSerializer
实际上与UI代码(基于System.ComponentModel
)构建的内容完全相同:
using System.ComponentModel;
using System.Windows.Forms;
static class Program
{
[System.STAThread]
static void Main()
{
Application.EnableVisualStyles();
using (var form = new Form())
using (var grid = new PropertyGrid())
{
grid.Dock = DockStyle.Fill;
var obj = new DefaultValueTestClass
{ // TODO - try with other numbers to
// see bold / not bold
Foo = 10000
};
// note in the grid the value is shown not-bold; that is
// because System.ComponentModel is saying
// "this property doesn't need to be serialized"
// - or to show it more explicitly:
var prop = TypeDescriptor.GetProperties(obj)["Foo"];
bool shouldSerialize = prop.ShouldSerializeValue(obj);
// ^^^ false, because of the DefaultValueAttribute
form.Text = shouldSerialize.ToString(); // win title
grid.SelectedObject = obj;
form.Controls.Add(grid);
Application.Run(form);
}
}
}
public class DefaultValueTestClass
{
[System.ComponentModel.DefaultValue(10000)]
public int Foo { get; set; }
}