XmlSerializer 定义默认值

发布于 2024-12-02 21:38:38 字数 494 浏览 0 评论 0原文

我们有一个包含一些用户设置的 xml 文档。我们刚刚添加了一个新设置(在旧版 xml 文档中找不到),XmlSerializer 自动将其设置为 false。 我尝试了 DefaultValueAttribute 但它不起作用。关于如何使默认值为 true 有什么想法吗?这是代码:

private bool _property = true;
[DefaultValueAttribute(true)]
public bool Property 
{
    get { return _property; }
    set
    {
        if (_property != value)
        {
            _property = value;
            this.IsModified = true;
        }
    }
}

谢谢!

We have an xml document with some user settings. We just added a new setting (which is not found in legacy xml documents) and the XmlSerializer automatically sets it to false.
I tried DefaultValueAttribute but it doesn't work. Any idea on how I can get the default value to be true? This is the code:

private bool _property = true;
[DefaultValueAttribute(true)]
public bool Property 
{
    get { return _property; }
    set
    {
        if (_property != value)
        {
            _property = value;
            this.IsModified = true;
        }
    }
}

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

满身野味 2024-12-09 21:38:38

DefaultValue 会影响序列化,就好像在运行时该属性具有与 DefaultValue 所说的值相匹配的值,那么 XmlSerializer 实际上不会将该元素写出(因为它是默认值)。

我不确定它是否会影响读取时的默认值,但在快速测试中似乎不会这样做。在您的场景中,我可能只是将其设置为带有支持字段的属性,并带有字段初始值设定项,使其变为“true”。恕我直言,我比 ctor 方法更喜欢这种方法,因为它将它与您为类定义或未定义的 ctor 解耦,但这是相同的目标。

using System;
using System.ComponentModel;
using System.Xml.Serialization;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        var serializer = new XmlSerializer(typeof(Testing));

        string serializedString;
        Testing instance = new Testing();
        using (StringWriter writer = new StringWriter())
        {
            instance.SomeProperty = true;
            serializer.Serialize(writer, instance);
            serializedString = writer.ToString();
        }
        Console.WriteLine("Serialized instance with SomeProperty={0} out as {1}", instance.SomeProperty, serializedString);
        using (StringReader reader = new StringReader(serializedString))
        {
            instance = (Testing)serializer.Deserialize(reader);
            Console.WriteLine("Deserialized string {0} into instance with SomeProperty={1}", serializedString, instance.SomeProperty);
        }
        Console.ReadLine();
    }
}

public class Testing
{
    [DefaultValue(true)]
    public bool SomeProperty { get; set; }
}

正如我在评论中提到的,关于 xml 序列化属性的页面 (http://msdn.microsoft.com/en-us/library/83y7df3e.aspx) 声称 DefaultValue 确实会使序列化程序在丢失时设置该值,但在此测试代码中并没有这样做(与上面类似,但只是反序列化 3 个输入)。

using System;
using System.ComponentModel;
using System.Xml.Serialization;
using System.IO;

class Program
{
    private static string[] s_inputs = new[]
    {
        @"<?xml version=""1.0"" encoding=""utf-16""?>
          <Testing xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" />",

        @"<?xml version=""1.0"" encoding=""utf-16""?>
          <Testing xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
              <SomeProperty />
          </Testing>",

        @"<?xml version=""1.0"" encoding=""utf-16""?>
          <Testing xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
              <SomeProperty>true</SomeProperty>
          </Testing>",
    };

    static void Main(string[] args)
    {
        var serializer = new XmlSerializer(typeof(Testing));

        foreach (var input in s_inputs)
        {
            using (StringReader reader = new StringReader(input))
            {
                Testing instance = (Testing)serializer.Deserialize(reader);
                Console.WriteLine("Deserialized string \n{0}\n into instance with SomeProperty={1}", input, instance.SomeProperty);
            }
        }
        Console.ReadLine();
    }
}

public class Testing
{
    [DefaultValue(true)]
    public bool SomeProperty { get; set; }
}

DefaultValue affects the serialization insofar as if at runtime the property has a value that matches what the DefaultValue says, then the XmlSerializer won't actually write that element out (since it's the default).

I wasn't sure whether it would then affect the default value on read, but it doesn't appear to do so in a quick test. In your scenario, I'd likely just make it a property with a backing field with a field initializer that makes it 'true'. IMHO I like that better than ctor approach since it decouples it from the ctors you do or don't have defined for the class, but it's the same goal.

using System;
using System.ComponentModel;
using System.Xml.Serialization;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        var serializer = new XmlSerializer(typeof(Testing));

        string serializedString;
        Testing instance = new Testing();
        using (StringWriter writer = new StringWriter())
        {
            instance.SomeProperty = true;
            serializer.Serialize(writer, instance);
            serializedString = writer.ToString();
        }
        Console.WriteLine("Serialized instance with SomeProperty={0} out as {1}", instance.SomeProperty, serializedString);
        using (StringReader reader = new StringReader(serializedString))
        {
            instance = (Testing)serializer.Deserialize(reader);
            Console.WriteLine("Deserialized string {0} into instance with SomeProperty={1}", serializedString, instance.SomeProperty);
        }
        Console.ReadLine();
    }
}

public class Testing
{
    [DefaultValue(true)]
    public bool SomeProperty { get; set; }
}

As I mentioned in a comment, the page on the xml serialization attributes (http://msdn.microsoft.com/en-us/library/83y7df3e.aspx) claims that the DefaultValue will indeed make the serializer set the value when it's missing, but it doesn't do so in this test code (similar to above, but just deserializes 3 inputs).

using System;
using System.ComponentModel;
using System.Xml.Serialization;
using System.IO;

class Program
{
    private static string[] s_inputs = new[]
    {
        @"<?xml version=""1.0"" encoding=""utf-16""?>
          <Testing xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" />",

        @"<?xml version=""1.0"" encoding=""utf-16""?>
          <Testing xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
              <SomeProperty />
          </Testing>",

        @"<?xml version=""1.0"" encoding=""utf-16""?>
          <Testing xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
              <SomeProperty>true</SomeProperty>
          </Testing>",
    };

    static void Main(string[] args)
    {
        var serializer = new XmlSerializer(typeof(Testing));

        foreach (var input in s_inputs)
        {
            using (StringReader reader = new StringReader(input))
            {
                Testing instance = (Testing)serializer.Deserialize(reader);
                Console.WriteLine("Deserialized string \n{0}\n into instance with SomeProperty={1}", input, instance.SomeProperty);
            }
        }
        Console.ReadLine();
    }
}

public class Testing
{
    [DefaultValue(true)]
    public bool SomeProperty { get; set; }
}
温柔一刀 2024-12-09 21:38:38

无论它如何记录工作,我也没有看到反序列化时分配 DefaultValue。对我来说,解决方案只是在类构造函数中设置默认值并放弃 DefaultValueAttribute。

Regardless of how it is documented to work, I also do not see DefaultValue being assigned when deserializing. The solution for me was simply set the default value within the class constructor and give up on DefaultValueAttribute.

剩余の解释 2024-12-09 21:38:38

关于斯科特的最后回复。

当未找到任何元素时,默认构造函数将任何数组属性设置为“null”。我已将该属性设置为新的空数组(因此是空数组的实例),但 XmlSerializer 在进行反序列化时会绕过此设置并将其设置为“null”。

类的示例:

[XmlElement("Dtc")]
public DtcMarketMapping[] DtcMarketMappingInstances
{
    get { return dtcMarketMappingInstances; }
    set { dtcMarketMappingInstances = value; }
}

但是,它可能是特定于数组的内容,并且您的答案对于在类的构造函数中为简单属性设置默认值仍然有效。

不管怎样,谢谢大家的回答。

About Scott's last reply.

The default constructor sets any array property to "null" when no elements are found. I've set the property to a new empty array (so an instance of an empty array), but the XmlSerializer bypasses this when doing its deserialization and sets it to "null".

Example of the class:

[XmlElement("Dtc")]
public DtcMarketMapping[] DtcMarketMappingInstances
{
    get { return dtcMarketMappingInstances; }
    set { dtcMarketMappingInstances = value; }
}

It might however be something specific to arrays and your answer is still valid about setting default values to simple properties in the class' constructor.

Anyways, thanks for the answers everyone.

小苏打饼 2024-12-09 21:38:38

在构造函数中设置默认值。如果该值存在于文件中,则仅在反序列化期间才会更改该值。

public class MySettingsClass
{
    public MySettingsClass()
    {
        _property = true;
    }

    private bool _property = true;
    public bool Property 
    {
        get { return _property; }
        set
        {
            if (_property != value)
            {
                _property = value;
                this.IsModified = true;
            }
        }
    }
}

Set the default value in the constructor. The value will only be changed during deserialize if it exists in the file.

public class MySettingsClass
{
    public MySettingsClass()
    {
        _property = true;
    }

    private bool _property = true;
    public bool Property 
    {
        get { return _property; }
        set
        {
            if (_property != value)
            {
                _property = value;
                this.IsModified = true;
            }
        }
    }
}
弥繁 2024-12-09 21:38:38

DefaultValueAttribute 实际上不会对您正在运行的代码执行任何操作。它(主要)由属性浏览器使用(例如,当您将对象绑定到 PropertyGrid 时)来了解默认值应该是什么,以便当该值不同于默认值时,它们可以执行一些“特殊”操作默认值。这就是 Visual Studio 中的属性网格如何知道何时将值设为粗体(表明它与默认值不同。

XmlSerializer 正在将您的 _property 字段设置为 false 因为这是 bool 的 .NET Framework 默认值。

实现此目的的最简单方法可能是使用默认类构造函数并在其中设置值。

The DefaultValueAttribute doesn't actually do anything to your running code. It is (mostly) used by property browsers (such as when you bind your object to a PropertyGrid) to know what the default value should be so they can do something "special" when the value is different than the default. That's how the property grid in Visual Studio knows when to make a value bold (showing that it's different than the default value.

The XmlSerializer is setting it your _property field to false because that is the .NET Framework default value for a bool.

The simplest way to accomplish this would probably be to use a default class constructor and set the value there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文