XmlSerializer определяет значение по умолчанию - PullRequest
4 голосов
/ 03 сентября 2011

У нас есть 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;
        }
    }
}

Спасибо!

Ответы [ 5 ]

9 голосов
/ 03 сентября 2011

DefaultValue влияет на сериализацию, если во время выполнения свойство имеет значение, совпадающее с тем, что говорит DefaultValue, тогда XmlSerializer не будет фактически записывать этот элемент (так как это значение по умолчанию).

Я не былНе уверен, повлияет ли это на значение по умолчанию при чтении, но в быстром тесте этого не происходит.В вашем сценарии я бы, вероятно, просто сделал его свойством с полем поддержки с инициализатором поля, которое делает его «истинным».ИМХО, мне нравится этот подход лучше, чем 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; }
}

Как я уже упоминал в комментарии,на странице атрибутов сериализации 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; }
}
3 голосов
/ 25 октября 2013

Независимо от того, как это задокументировано для работы, я также не вижу назначения DefaultValue при десериализации. Для меня решение было просто установить значение по умолчанию в конструкторе класса и отказаться от DefaultValueAttribute.

1 голос
/ 04 июня 2012

О последнем ответе Скотта.

Конструктор по умолчанию устанавливает для любого свойства массива значение «ноль», если элементы не найдены. Я установил для свойства новый пустой массив (например, экземпляр пустого массива), но XmlSerializer обходит это при выполнении десериализации и устанавливает его в «null».

Пример класса:

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

Однако это может быть что-то особенное для массивов, и ваш ответ все еще действителен в отношении установки значений по умолчанию для простых свойств в конструкторе класса.

В любом случае, спасибо всем за ответы.

0 голосов
/ 30 ноября 2016

Установить значение по умолчанию в конструкторе. Значение будет изменено только во время десериализации, если оно существует в файле.

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;
            }
        }
    }
}
0 голосов
/ 03 сентября 2011

DefaultValueAttribute на самом деле ничего не делает с вашим работающим кодом. Он (в основном) используется браузерами свойств (например, когда вы связываете свой объект с PropertyGrid), чтобы знать, каким должно быть значение по умолчанию, чтобы они могли сделать что-то «особенное», когда значение отличается от значения по умолчанию. Вот как сетка свойств в Visual Studio знает, когда следует сделать значение жирным (показывая, что оно отличается от значения по умолчанию.

XmlSerializer устанавливает для вашего поля _property значение false, поскольку это значение по умолчанию .NET Framework для bool.

Самый простой способ сделать это, вероятно, использовать конструктор класса по умолчанию и установить значение там.

...