【问题标题】:XmlSerializer define default valueXmlSerializer 定义默认值
【发布时间】:2011-09-03 01:35:21
【问题描述】:

我们有一个包含一些用户设置的 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;
        }
    }
}

谢谢!

【问题讨论】:

    标签: c# xmlserializer


    【解决方案1】:

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

    我不确定它是否会影响读取时的默认值,但在快速测试中似乎不会这样做。在您的场景中,我可能只是将其设置为具有支持字段的属性,该属性具有使其“真实”的字段初始化程序。恕我直言,我比 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; }
    }
    

    【讨论】:

    • 你说得对,这行不通。起作用的只是按照下面其他帖子中的建议在类构造函数中设置默认值。
    【解决方案2】:

    不管它是如何工作的,我也没有看到在反序列化时分配 DefaultValue。我的解决方案是简单地在类构造函数中设置默认值并放弃 DefaultValueAttribute。

    【讨论】:

    • 这是解决 DefaultValueAttribute 不起作用的好方法。
    • 如果您在属性上设置了默认值并且该属性缺失,它会按预期工作。如果您在元素上设置了默认值并且元素 content 为空,则它会按预期工作;但是,如果元素 缺失,则在反序列化时分配一个空值。这是标准的 XML 行为,没有什么用处。在构造函数中设置默认值更明智。
    【解决方案3】:

    关于 Scott 的最后回复。

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

    类示例:

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

    然而,它可能是特定于数组的东西,您的回答仍然适用于在类的构造函数中为简单属性设置默认值。

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

    【讨论】:

    • 用 xml 读/写数组真的很尴尬。也许如果它是在构造函数中分配的固定大小的数组,但到目前为止,我最终对任何作为 XmlElement 的字段使用列表而不是数组,因为它们可以正常工作。
    【解决方案4】:

    在构造函数中设置默认值。该值只有在文件中存在时才会在反序列化期间更改。

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

    【讨论】:

      【解决方案5】:

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

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

      实现这一点的最简单方法可能是使用默认的类构造函数并在那里设置值。

      【讨论】:

      • 它对正在运行的代码没有任何作用是不正确的。如果没有默认值,在某些情况下甚至无法反序列化。如果您查看generated code。 DefaultValue 在反序列化时没有设置默认值,这很不直观。但是,它确实会导致生成的代码跳过空元素。
      • 我投了赞成票,因为您对 PropertyGrid 提出了一个很好的观点。但是 XmlSerializer 接缝使用 DefaultValueAttribute 也可能让人头疼。有时我想要我的 propertyGrid 的 DefaultValue,但仍想序列化我的值(在任何情况下)以确保对我的 DefaultValue 的任何更改(将来)都会让代码像以前一样运行。
      • 序列化时,如果值匹配DefaultValueAttribute,则属性或元素不会被序列化。如果是元素,这其实是XmlSerializer中的一个bug,因为元素可能有空的content,但一定不能省略;如果 XML 模式中的 minOccurs=0 被省略,则仅不是错误。
      猜你喜欢
      • 2011-05-12
      • 1970-01-01
      • 1970-01-01
      • 2010-11-08
      • 2021-03-04
      • 2021-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多