1

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

1 回答 1

0

实现默认值是你的工作;[DefaultValue]只是说“这是默认设置,你不必担心这个” - 它不适用。这不仅适用于XmlSerializer,还适用于其所属的核心System.ComponentModelAPI [DefaultValue](驱动诸如粗体/非粗体PropertyGrid等内容)

基本上:

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


下面是一些 UI 代码,显示它实际上在做的事情与 UI 代码(构建在)一直在做XmlSerializer的事情完全相同: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; }
}
于 2013-08-28T12:42:27.717 回答