WCF DataContract serialization of read-only properties?
serialization, wcf
Solution
If you use the DataContractSerializer (which is the default for WCF), you can serialize anyhting that's decorated with the `[DataMember]` attribute - even a read-only field:
[DataContract]
public class VirtualMachineTemplate : VirtualMachineTemplateBase, IXmlPicklable, IEnableLogger
{
[DataMember]
ulong _SizeInBytes;
}
But you need to use the DataContractSerializer - not the XML serializer. The XML serializer can ONLY serialize public properties (and it will, unless you put a [XmlIgnore] on them).
The DataContractSerializer is different:
- it doesn't need a parameter-less default constructor
- it will only serialize what you explicitly mark with `[DataMember]`
- but that can be anything - a field, a property, and of any visibility (private, protected, public)
- it's a bit faster than XmlSerializer, but you don't get a lot of control over the shape of the XML - you only get a say in what's included
See this blog post and this blog post for a few more tips and tricks.
Marc
Problem
Whenever I use WCF, I always try to make immutable classes that end up going over the wire (i.e. parameters set in constructor, properties are read-only). However, this gets in the way of WCF serialization, which demands that all properties be Public get/set (which makes sense, because it has to deserialize them) Even in this related post, I see that their solution ended up making everything Public, which violates my sense of good programming. Is there any way around this? Do I have to just settle for this solution or something like popsicle immutability and be happy with it? The other thing I tried was something like this, where I'd have a base class for everything and a derived class that made the set useless: ``` /// <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 { } } } ```