2009-08-27 15 views
14

Siempre que uso WCF, siempre trato de crear clases inmutables que terminan pasando por el cable (es decir, los parámetros establecidos en el constructor, las propiedades son de solo lectura). Sin embargo, esto interfiere con la serialización de WCF, que exige que todas las propiedades sean Públicas get/set (lo cual tiene sentido, porque tiene que deserializarlas)WCF DataContract serialización de propiedades de solo lectura?

Incluso en this related post, veo que su solución terminó haciendo que todo Público, lo cual viola mi sentido de buena programación. ¿Hay alguna forma de evitar esto? ¿Tengo que conformarme con esta solución o algo así como la inmutabilidad de las paletas y ser feliz con eso?

La otra cosa que probé era algo como este, donde tendría una clase base para todo y una clase derivada que hizo el conjunto inútil:

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

Respuesta

15

Si utiliza DataContractSerializer (que es el predeterminada para WCF), puede serializar anyhting que está decorado con el atributo [DataMember] - incluso un campo de sólo lectura:

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

pero hay que usar DataContractSerializer - no el serializador XML. El serializador XML SOLO puede serializar propiedades públicas (y lo hará, a menos que ponga un [XmlIgnore] en ellas).

DataContractSerializer es diferente:

  • que no necesita un constructor predeterminado sin parámetros
  • lo hará solamente serializar lo que se marca de forma explícita con [DataMember]
  • , sino que puede ser cualquier cosa - un campo, una propiedad y cualquier visibilidad (privada, protegida, pública)
  • es un poco más rápido que XmlSerializer, pero no se tiene mucho control sobre la forma del XML - sólo tienes que decir en lo que está incluido

ver este blog post y esto blog post para unos pocos más consejos y trucos.

Marc

+12

No, aún necesita incluir el conjunto o falla. – Craig

+0

Puede establecer SerializeReadOnlyTypes en true en DataContractSerializerSettings. –

+0

Aw, los enlaces a las publicaciones del blog están muertos ahora :( –

3

para asegurar tanto la inmutabilidad y fácil aplicación, al mismo tiempo añadir un regulador privada por la propiedad de servir deserialización. Muchas cosas pasan debajo del capó, pero funciona.

Cuestiones relacionadas