Сериализатор разработан таким образом, что, если он сериализует объект, он должен иметь возможность прочитать его обратно.Если вы попытаетесь сериализовать объект с объявленным типом «Base», но фактическим типом «Derived» (см. Пример ниже), если вы хотите иметь возможность считывать из сериализованного объекта экземпляр «Derived»,вам нужно как-то аннотировать XML-код, экземпляр которого не относится к тому типу, который был объявлен.
[DataContract]
public class MyType
{
[DataMember]
public object obj = new Derived();
}
Сериализованная версия этого типа будет выглядеть примерно так, как показано ниже:
<MyType>
<obj actualType="Derived">
<!-- fields of the derived type -->
</obj>
</MyType>
Когда тип десериализуется, сериализатор будет смотреть на атрибут «actualType» (не фактическое имя), и ему нужно будет найти этот тип, инициализировать его и установить его свойства.Это потенциальная проблема безопасности, позволяющая сериализатору (поскольку в Silverlight life это доверенная сборка и имеет больше «прав», чем у обычного пользовательского кода) для создания произвольного типа, так что это одна из причин ограничения типов, которые можно десериализовать.И исходя из конструкции сериализатора (если мы можем сериализовать его, мы должны быть в состоянии десериализовать его), сериализация также завершается неудачей по этой причине.
Другая проблема заключается в том, что сериализованные данные частоиспользуется для связи между различными службами, на разных компьютерах и, возможно, на разных языках.Возможно (и часто это так), что у вас есть класс в пространстве имен на клиенте, который имеет контракт данных , аналогичный классу на стороне сервера, но они имеют разные имена и / или находятсяв разных пространствах имен.Поэтому простое добавление имени типа CLR в атрибут «actualType» также не сработает в этом сценарии (атрибут [KnownType] помогает serialzier сопоставить имя / пространство имен контракта данных с фактическим типом CLR).Кроме того, если вы говорите со службой на другом языке / платформе (например, Java), имена типов CLR даже не имеют смысла.
Другое более подробное объяснение дано в посте http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx - здесь говорится о [ServiceKnownType] вместо [KnownType], но принципы те же.
Наконец, по вашему вопросу: нарушает ли этот ОО-принцип?Да, этот принцип нарушен, это цена, которую нужно заплатить за возможность потерять связь между клиентом и сервисами в вашем распределенном (сервис-ориентированном) приложении.