Почему я не могу иметь DataMember с `IsRequired=true`, если мой DataContract равен`IsReference=true`
У меня есть класс, ClassA
который имеет свойство, которое содержит типы ClassB
который имеет поле типа ClassA
, Когда я попытался сериализовать это через WCF, я получил исключение из-за рекурсивного характера этого. Решение было добавить IsReference=true
к определению контракта данных ClassA
,
Это здорово, но у меня есть члены ClassA
которые отмечены DataMember(IsRequired=true)
атрибут и как только я добавил IsReference=true
Затем он пожаловался, что вещи не могут быть обоими IsReference=true
и есть члены, которые являются IsRequired=true
,
Я не могу понять, почему это так, и я хотел бы знать, есть ли обходной путь для этого?
Я хотел бы объявить мои камеры данных так, чтобы они требовались в XML?
Я уже видел этот пост, но ответ до сих пор не ясен для меня. Если я хочу предотвратить выдачу значений по умолчанию, тогда я могу использовать EmitDefaultValues =false вместе с IsRequired=true (что я в любом случае хочу сделать). Есть ли другой обходной путь?
1 ответ
Рассмотрим сценарий десериализации. У вас есть набор XML, который читает DataContractSerializer. Представьте, что вы имеете дело с типом Foo, который помечен как IsReference = true и IsRequired = true.
Сериализатор обнаруживает поле foo1 типа Foo. Теперь, это означает, что XML может сказать что-то вроде следующего:
<foo1 ref="1" /?
Сериализатор десериализует foo1 в null, но помните, что он ссылался на объект, которого у него еще нет. Сериализатор продолжает десериализацию оставшихся полей. В конце концов, он сталкивается с другим полем, как показано ниже. Ага, он видит объект, на который foo1 ссылался ранее - объект с идентификатором 1.
<foo2 id="1"> <datamember1> ... </datamember1> <datamember2> ... </datamember2> </foo2>
Когда он встречает id="1", сериализатор возвращается и исправляет foo1, чтобы указать на foo2.
Однако, foo2 может никогда не существовать. Другими словами, foo1 может ссылаться на идентификатор, который не существует нигде в XML. У сериализатора нет возможности узнать это наверняка, пока он полностью не десериализует остальную часть графика.
Я надеюсь, что вы начинаете видеть проблему. Если тип был и IsReference, и IsReequired, сериализация больше не сможет гарантировать, что природа типа IsRequired будет соблюдаться во время десериализации. Он больше не может быстро потерпеть неудачу, если требуемый элемент не существует, потому что он не может быть уверен, существует ли он.