Триггерная функция на десериализации

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

Существует ли способ, которым я могу настроить вызов функции, который будет инициирован на десериализации?

8
задан Tom Savage 24 May 2010 в 10:07
поделиться

4 ответа

Вы описываете [OnDeserialized]

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

Другой вариант - вручную реализовать IXmlSerializable , но это сложно .

6
ответ дан 5 December 2019 в 22:16
поделиться

Поскольку объекту, который может быть сериализован в формате 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;
    }
}
1
ответ дан 5 December 2019 в 22:16
поделиться

- Изменить:

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

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

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

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

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

1
ответ дан 5 December 2019 в 22:16
поделиться

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

-2
ответ дан 5 December 2019 в 22:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: