简体   繁体   English

XmlSerializer定义默认值

[英]XmlSerializer define default value

We have an xml document with some user settings. 我们有一个带有一些用户设置的xml文档。 We just added a new setting (which is not found in legacy xml documents) and the XmlSerializer automatically sets it to false . 我们刚刚添加了一个新设置(在旧版xml文档中找不到), XmlSerializer自动将其设置为false I tried DefaultValueAttribute but it doesn't work. 我尝试过DefaultValueAttribute但它不起作用。 Any idea on how I can get the default value to be true ? 关于如何让默认值为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! 谢谢!

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). DefaultValue会影响序列化,因为如果在运行时属性的值与DefaultValue所说的值匹配,那么XmlSerializer实际上不会写出该元素(因为它是默认值)。

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'. 在你的场景中,我可能只是将它作为一个带有支持字段的属性,其中字段初始值设定项使其为“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. 恕我直言,我比ctor方法更喜欢它,因为它将它与你做或不为课程定义的ctors分离,但它是同一个目标。

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). 正如我在评论中提到的,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; }
}

Regardless of how it is documented to work, I also do not see DefaultValue being assigned when deserializing. 无论如何记录它的工作原理,我也没有看到在反序列化时分配DefaultValue。 The solution for me was simply set the default value within the class constructor and give up on DefaultValueAttribute. 我的解决方案只是在类构造函数中设置默认值并放弃DefaultValueAttribute。

About Scott's last reply. 关于斯科特的最后回复。

The default constructor sets any array property to "null" when no elements are found. 当没有找到元素时,默认构造函数将任何数组属性设置为“null”。 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". 我已经将属性设置为一个新的空数组(所以是一个空数组的实例),但XmlSerializer在进行反序列化时绕过它并将其设置为“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. 无论如何,感谢大家的答案。

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

The DefaultValueAttribute doesn't actually do anything to your running code. DefaultValueAttribute实际上对您正在运行的代码没有任何作用。 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. 它(主要)由属性浏览器使用(例如当您将对象绑定到PropertyGrid )以了解默认值应该是什么,以便当值不同于默认值时,它们可以执行“特殊”操作。 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. 这就是Visual Studio中的属性网格如何知道何时使值变为粗体(表明它与默认值不同)。

The XmlSerializer is setting it your _property field to false because that is the .NET Framework default value for a bool . XmlSerializer将其_property字段设置为false因为这是bool的.NET Framework默认值。

The simplest way to accomplish this would probably be to use a default class constructor and set the value there. 完成此操作的最简单方法可能是使用默认的类构造函数并在那里设置值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM