2009-08-27 5 views
14

Всякий раз, когда я использую WCF, я всегда стараюсь сделать неизменяемые классы, которые в конечном итоге переходят через провод (т. Е. Параметры, заданные в конструкторе, свойства доступны только для чтения). Тем не менее, это мешает сериализации WCF, которая требует, чтобы все свойства были Public get/set (что имеет смысл, поскольку оно должно десериализовать их)WCF DataContract сериализация свойств только для чтения?

Даже в this related post, я вижу, что их решение в итоге все сделало Общественность, которая нарушает мое чувство хорошего программирования. Есть ли способ обойти это? Должен ли я просто согласиться на это решение или что-то вроде неизменности эскимосов и быть довольным этим?

Другая вещь, которую я попытался было что-то вроде этого, где я есть базовый класс для всего и производного класса, который сделал набор бесполезно:

/// <summary> 
/// This represents a discovered virtual-machine template that can be 
/// instantiated into a RunningVirtualMachine 
/// </summary> 
[DataContract] 
[XmlRoot("VMTemplate")] 
public class VirtualMachineTemplateBase 
{ 
    [DataMember] 
    public virtual ulong SizeInBytes { get; set; } 
} 

/// <summary> 
/// This class is the real guts of VirtualMachineTemplate that we're hiding 
/// from the base class. 
/// </summary> 
[XmlInclude(typeof(VirtualMachineTemplateBase))] 
public class VirtualMachineTemplate : VirtualMachineTemplateBase, IXmlPicklable, IEnableLogger 
{ 
    ulong _SizeInBytes; 
    public override ulong SizeInBytes { 
     get { return _SizeInBytes; } 
     set { } 
    } 
} 

ответ

15

Если вы используете DataContractSerializer (который является по умолчанию для WCF), вы можете сериализовать anyhting, который декорированный с атрибутом [DataMember] - даже только для чтения поле:

[DataContract] 
public class VirtualMachineTemplate : VirtualMachineTemplateBase, IXmlPicklable, IEnableLogger 
{ 
    [DataMember] 
    ulong _SizeInBytes; 
} 

Но вы должны использовать DataContractSerializer - не XML сериалайзер. Сериализатор XML может ТОЛЬКО сериализовать общедоступные свойства (и это произойдет, если вы не поместите на них [XmlIgnore]).

DataContractSerializer отличается:

  • не нужен параметр меньше конструктор по умолчанию
  • он будет только сериализации, что вы явно помечать [DataMember]
  • но это может быть что угодно - поле, свойство и любую видимость (private, protected, public)
  • это немного быстрее, чем XmlSerializer, но вы не получаете большого контроля над формой XML - вы получите только слово в том, что включено

blog post Смотрите этот и этот blog post еще несколько советов и хитростей.

Марк

+12

Нет, вам все равно нужно включить набор или он не работает. – Craig

+0

Вы можете установить SerializeReadOnlyTypes в true в DataContractSerializerSettings. –

+0

Aw, ссылки на сообщения блога сейчас мертвы :( –

3

Чтобы обеспечить как неизменность и легкое внедрение в то же время добавить частный сеттера для свойства служить десериализации. Много происходит под капотом, но оно работает.

Смежные вопросы