2010-05-24 8 views
8

У меня есть класс с рядом полей, которые обычно вычисляются в конструкторе из других данных в классе. Они не сериализуются в XML, потому что любые изменения остальной части данных, скорее всего, потребуют их пересчета.Функция триггера при десериализации

Есть ли способ настроить вызов функции для запуска при десериализации?

ответ

5

То, что вы описываете [OnDeserialized]

XmlSerializer не поддерживает методы сериализации обратного вызова (по крайней мере, не в MS .NET; моно могут быть различными). В зависимости от ваших потребностей вы можете попробовать DataContractSerializer, который делает поддерживает обратные вызовы сериализации (как и многие другие сериализаторы). В противном случае ваш лучший подход может состоять в том, чтобы просто использовать свой собственный общедоступный метод, который вы вызываете вручную.

Другой вариант - ручное оснащение IXmlSerializable, но это hard.

+0

Это то, что я искал. Однако разочарование это не работает с XML. Думаю, я просто сделаю заметку, чтобы вызвать метод вручную. Это просто проще. –

1

- Edit:

Просто подтвердили, что, как комментатор ниже говорит, процесс сериализации XML не попал метод «OnDeserialized'-атрибуты объявлены. Какой позор.

- Предыдущий ответ:

Да, действительно, посмотрите here.

Особый интерес представляет бы атрибут OnDeserialized, обсуждаемый here.

Возможно, стоит отметить, что в зависимости от используемого метода сериализации (я думаю) будет вызываться конструктор no-arg. Очевидно, это произойдет до что-нибудь еще. Так что это, вероятно, не совсем полезно.

+1

... который не используется 'XmlSerializer'. –

+0

@Marc Интересно, почему? Он не упоминает, что в документации ... –

+1

Он также не упоминает, что он * поддерживает их ;-p –

1

Поскольку для объекта, который может быть сериализован XML, нужен открытый конструктор без параметров, кажется, что у вас есть дыра в дизайне вашего класса даже до того, как вы нажмете сериализацию XML.

Лично я бы пошел с ленивым вычислением этих полей. Храните флаг внутри класса, независимо от того, были ли вы рассчитаны поля или нет, и установите для этого поля значение, обозначающее «устаревшее», когда изменяется какое-либо из свойств, используемых в вычислении. Затем в свойствах, возвращающих вычисленные значения, проверьте, нужно ли пересчитывать, прежде чем возвращать значение.

Это будет работать независимо от сериализации XML или нет.

пример:

[XmlType("test")] 
public class TestClass 
{ 
    private int _A; 
    private int? _B; 

    public TestClass() 
     : this(0) 
    { 
    } 

    public TestClass(int a) 
    { 
     _A = a; 
    } 

    [XmlAttribute("a")] 
    public int A 
    { 
     get { return _A; } 
     set { _A = value; _B = null; } 
    } 

    [XmlIgnore] 
    public int B 
    { 
     get { if (_B == null) Recalculate(); return _B; } 
     set { _B = value; } 
    } 

    private void Recalculate() 
    { 
     _B = _A + 1; 
    } 
} 
+0

У меня действительно есть конструктор без параметров, t действительно ничего полезного, потому что данных пока нет. Я бы также подумал, что это будет вызвано до десериализации, поэтому я не могу много сделать там. Однако я рассмотрю ваше предложение. –

-3

Вы можете реализовать интерфейс IDeserializationCallback

+0

Посмотрите мои комментарии к @silky; 'XmlSerializer' не поддерживает обратные вызовы сериализации (не через интерфейсы, а не через атрибуты). –

+0

' IDeserializationCallback' не используется XmlSerializer – sll

Смежные вопросы