У меня есть класс со многими полями, которые обычно вычисляются в конструкторе от других данных в классе. Они не сериализируются к XML, потому что любые изменения в остальной части данных, вероятно, потребуют своего перерасчета.
Существует ли способ, которым я могу настроить вызов функции, который будет инициирован на десериализации?
Вы описываете [OnDeserialized]
XmlSerializer
не поддерживает методы обратного вызова сериализации (по крайней мере, не в MS .NET; моно может быть другим). В зависимости от ваших потребностей вы можете попробовать DataContractSerializer
, который поддерживает обратные вызовы сериализации (как и ряд других сериализаторов). В противном случае ваш лучший подход может заключаться в том, чтобы просто иметь собственный общедоступный метод, который вы вызываете вручную.
Другой вариант - вручную реализовать IXmlSerializable
, но это сложно .
Поскольку объекту, который может быть сериализован в формате 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;
}
}
- Изменить:
Только что подтвердил, что, как говорит нижеприведенный комментатор, процесс сериализации xml не затрагивает метод, объявленный атрибутом 'OnDeserialized'. Какая жалость.
- Предыдущий ответ:
Да, действительно, посмотрите здесь .
Особый интерес представляет атрибут OnDeserialized
, обсуждаемый здесь .
Возможно, стоит отметить, что в зависимости от используемого метода сериализации (я думаю) будет вызываться ваш конструктор без аргументов. Очевидно, это произойдет до того, как будет установлено что-либо еще. Так что это, наверное, не совсем полезно.
Вы можете реализовать интерфейс IDeserializationCallback