Подтвердить что ты не робот

Почему методы обработки вызовов сериализации не являются виртуальными?

У меня есть метод десериализации (украшенный атрибутом [OnDeserialized()]), который я хочу переопределить в производном классе. Когда я пытаюсь сделать это, я получаю следующую ошибку времени выполнения:

Необработанное исключение типа "System.TypeLoadException".... Тип "BaseObj" в сборке... имеет метод "OnDeserialization", который является либо статическим, либо виртуальным, либо абстрактным, либо обобщенным, но помечен как метод обратного вызова сериализации.

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

Исходя из предложения в комментарии здесь, я прибегал к вызову отдельной виртуальной функции из метода OnDeserialization следующим образом:

[Serializable()]
public class BaseObj
{   
    protected string obj { get; set; } 

    [OnDeserialized()]
    public void OnDeserializedMethod(StreamingContext context)
    {
        //call the virtual method because deserialization callbacks can’t be virtual
        onDeserialized(context);
    }    
    virtual protected void onDeserialized(StreamingContext context)
    {
        obj = "This value was deserialized by the base class.";
    }   
}
[Serializable()]
public class DerivedObj : BaseObj
{    
    override protected void onDeserialized(StreamingContext context)
    {
        obj = "This value was deserialized by the derived class.";
    }    
}

Кажется, что это работает нормально, но кажется, скорее, "kludgey". Это мой единственный вариант? Почему метод обратного вызова сериализации не может быть виртуальным?

4b9b3361

Ответ 1

Так как BinaryFormatter и DataContractSerializer не вызывают конструкторы при десериализации, OnDeserializedAttribute позволяет выполнять операции, которые вы обычно делаете в конструкторе, например. инициализация состояния. Методы, отмеченные этим атрибутом, также выполняются в том же порядке, что и конструкторы: сначала base, затем производные.

Итак, для целей десериализации вы можете обрабатывать эти методы как конструкторы.

И виртуальные конструкторы не разрешены в С#.

Ответ 2

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

[DataContract]
class Base
{
    [OnDeserialized]
    //cannot be virtual
    protected void OnDeserializedBase()
    {
        //base deserialization
    }
}

[DataContract]
public class Derived : Base
{
    [OnDeserialized]
    //cannot be virtual
    OnDeserializedDerived()
    {
        //Derived deserialization
    }
}

Base b = new DataContractJsonSerializer(typeof(Derived)).ReadObject(stream);

Я обнаружил, что OnDeserializedBase и OnDeserializedDerived будут вызываться по очереди. Даже если в производном классе НЕТ OnDeserialized, Базовый класс OnDeserializedBase все равно будет вызван.

Если это так, виртуальный метод не имеет смысла. Потому что, чтобы получить выгоду от виртуального метода, вам нужно передать производный объект в базовый объект и вызвать этот base.virtualMethod(). Там никогда не бывает возможности сделать это таким образом. Но вам не нужно беспокоиться о потере функциональности OnDeserialized даже после десериализации производного класса.

Поэтому после теста я с радостью поступлю так, как отправил.