WCF DataContract сериализация свойств только для чтения? - PullRequest
14 голосов
/ 28 августа 2009

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

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

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

/// <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 { }
    }
}

Ответы [ 2 ]

15 голосов
/ 28 августа 2009

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

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

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

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

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

См. сообщение в блоге и сообщение в блоге , где вы найдете несколько советов и подсказок.

Марк

3 голосов
/ 22 ноября 2013

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...