Анализатор обнаружил незапечатанный класс, реализующий интерфейс 'ISerializable', но не реализующий виртуальный метод 'GetObjectData'. Это может привести к ошибкам сериализации в производных классах.
Рассмотрим пример. Пусть у нас имеются объявления базового и производного классов следующего вида:
[Serializable] class Base : ISerializable { .... public void GetObjectData(SerializationInfo info, StreamingContext context) { .... } } [Serializable] sealed class Derived : Base { .... public new void GetObjectData(SerializationInfo info, StreamingContext context) { .... } }
Где-то есть код, выполняющий сериализацию объекта:
void Foo(BinaryFormatter bf, MemoryStream ms) { Base obj = new Derived(); bf.Serialize(ms, obj); ms.Position = 0; Derived derObj = (Derived)bf.Deserialize(ms); }
В таком случае сериализация выполнится неправильно из-за того, что будет вызван метод 'GetObjectData' не производного, а базового класса. Следовательно, члены производного класса не будут сериализованы. Если при десериализации из объекта 'SerializationInfo' будут извлекаться значения членов, добавляемых в методе 'GetObjectData' производного класса, будет сгенерировано исключение, так как объект 'SerializationInfo' не будет содержать запрашиваемых значений.
Для решения проблемы необходимо определить метод 'GetObjectData' в базовом классе с модификатором 'virtual', а в производном – 'override'. Тогда корректный код может выглядеть так:
[Serializable] class Base : ISerializable { .... public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { .... } } [Serializable] sealed class Derived : Base { .... public override void GetObjectData(SerializationInfo info, StreamingContext context) { .... } }
Если в базовом классе определена только явная реализация интерфейса, стоит также добавить неявную реализацию виртуального метода 'GetObjectData'. Рассмотрим пример. Предположим, что у нас имеются определения классов следующего вида
[Serializable] class Base : ISerializable { .... void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { .... } } [Serializable] sealed class Derived : Base, ISerializable { .... public void GetObjectData(SerializationInfo info, StreamingContext context) { .... } }
В таком случае из производного класса будет невозможно обратиться к методу 'GetObjectData' базового класса, а значит, часть членов не будет сериализована. Для исправления ошибки помимо явной реализации в базовый класс необходимо добавить неявную реализацию виртуального метода 'GetObjectData'. Тогда исправленный код может выглядеть так:
[Serializable] class Base : ISerializable { .... void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { GetObjectData(info, context); } public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { .... } } [Serializable] sealed class Derived : Base { .... public override void GetObjectData(SerializationInfo info, StreamingContext context) { .... base.GetObjectData(info, context); } }
Если же подразумевается, что у класса не должно быть наследников, следует добавить модификатор 'sealed' к объявлению класса, что сделает его запечатанным.