2015-06-25 5 views
2

У меня есть класс, который представляет собой кучу настроек:Как перезаписать коллекции по умолчанию на десериализации

public class Settings 
{ 
    public Settings() 
    { 
     InnerSettings = new List<InnerSettings>(); 
     //this is the settings i want to have by default 
     InnerSettings.Add(new InnerSettings()); 
    } 
    [XmlArray] 
    public List<InnerSettings> InnerSettings {get; set;} 
} 

Теперь, когда я десериализацию этого объекта, то InnerSettings из XML добавляется в List поверх элементов которые были созданы по умолчанию для конструктора Settings(). Есть ли простой способ сказать десериализатору, что я хочу вместо этого переписать коллекцию, удалив элементы по умолчанию?

+0

Вы десериализации все, кроме 'InnerSettings'? –

+0

@YuvalItzchakov Я хочу десериализовать все, но я не хочу, чтобы 'InnerSettings', добавленный в конструктор' default() 'по умолчанию, присутствовал в десериализованном объекте (если они не представлены в XML также). –

+0

Создайте базовый класс с настройками по умолчанию. У вас класс Settings наследует базовый класс. – jdweng

ответ

1

XML Serializer не поддерживает обратный вызов и имеет класс XmlSerializer. Есть несколько методов, которые вы можете переопределить. Давайте посмотрим на некоторые (грязные) обходные пути:

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

public class Settings { 
    private Settings() { 
     // Called by XmlDeserializer 
    } 

    private Settings(int dummy) { 
     // Called by factory method 
     InnerSettings = new List<InnerSettings> { new InnderSettings(); } 
    } 

    public static Settings Create() { 
     return new Settings(0); 
    } 
} 

2) Удаление элементов после того, как объект был десериализации. Создайте свой собственный XmlSerializer для этого:

public class SettingsXmlSerializer : XmlSerializer { 
    protected override object Deserialize(XmlSerializationReader reader) { 
     var settings = (Settings)base.Deserialize(reader); 
     settings.InnerSettings.RemoveAt(0); 

     return settings; 
    } 
} 

3) Он должен быть правильный способ сделать это, но это не так просто для сложных типов: длинную работу IXmlSerializable реализации ...

+1

Спасибо. Я закончил создание статического свойства в классе «Настройки», чтобы сохранить пресет по умолчанию и удалить эту логику из конструктора по умолчанию. Интересно, почему сериализация работает таким образом. Почему он добавляет элементы в существующую коллекцию, insted для ее воссоздания? Каков прецедент для такого поведения? –

+1

Поскольку XML-сериализация просто вызывает конструктор по умолчанию для создания нового объекта. Затем заполняет этот экземпляр данными из файла XML. Он делает код инициализации _easier_, но встречается интуитивно, если вы привыкли к другим механизмам сериализации. –

+0

Хорошо, да, вызов конструктора по умолчанию до десериализации имеет смысл. Что не совсем понятно, так это то, что вместо вызова set accessor в свойствах «List », перезаписывая коллекцию, десериализатор фактически вызывает метод «IList.Add». Это не влияет на меня, как на более легкую вещь, и не похоже на то, как десериализатор рассматривает свойства других типов. –