2010-03-22 16 views
12

Estoy tratando de devolver un tipo complejo de un método de servicio en WCF. Estoy usando C# y .NET 4. Este tipo complejo está destinado a ser invariante (del mismo modo que las cadenas .net). Además, el servicio solo lo devuelve y nunca lo recibe como argumento.WCF DataContract con propiedades de solo lectura

Si trato de definir solo getters en las propiedades me sale un error de tiempo de ejecución. Supongo que esto se debe a que ningún setter causa que la serialización falle. Aún así, creo que este tipo debería ser invariante.

Ejemplo:

[DataContract] 
class A 
{ 
    [DataMember] 
    int ReadOnlyProperty {get; private set;} 
} 

El servicio no puede cargar debido a un problema con la serialización.

¿Hay alguna manera de hacer las propiedades de solo lectura en un WCF DataContract? Tal vez al reemplazar el serializador? ¿Si es así, cómo? Si no, ¿qué sugieres para este problema?

Gracias,
Asaf

+0

Usted puede ser capaz de utilizar los campos de sólo lectura (* no propiedades *) e inicializar en la construcción de su clase. Además ..., posible duplicado: http://stackoverflow.com/q/1873741/945456 –

+0

Esto es aún más importante hoy en día con el cambio a clases inmutables y el soporte de C# -6.0 para propiedades de solo-implementación implementadas automáticamente. – binki

Respuesta

1

DataMember Field no puede ser de solo lectura, porque wcf no serializa el objeto tal cual y cada vez que se inicia la deserialización, se crea una nueva instancia de objeto, utilizando el constructor predeterminado. Los despachadores usan setters para establecer valores de campo después de la deserialización.

Pero todo el texto superior puede ser un gran error :)

para que sean realmente de sólo lectura, hacen que la lógica del servidor, la validación de valores de campo Thiss.

-1

¿Usted ha intentado hacer el colocador privada?

Algo así como:

public string MyProperty 
{ 
get; 
private set; 
} 
+0

Sí. Ese es exactamente mi problema. –

+0

¿Así que esto lo arregló? O esto es lo que estabas intentando? –

+0

No funciona. Si hago de MyProperty un [DataMember] obtengo un error de tiempo de ejecución causado, a mi entender, por la serialización. Sucede tan pronto como se carga el servicio, ni siquiera durante una operación del cliente. –

13

poner [DataMember] en el campo de respaldo, no será necesario un regulador.

+0

Pero no lo hará ser de solo lectura, y no expresar que debe ser de solo lectura. –

+4

nunca será de solo lectura. El contrato de datos cuando se transfiere a través del cable es solo un XML. No se puede hacer una pieza de XML de solo lectura. No se puede ** hacer * * Quien esté al otro lado del cable no cambie su valor. Simplemente no funciona así. –

+0

Simplemente podría ignorar el valor si se pasa al servicio? Por solo lectura quiere decir que el servicio solo regresa ? –

7

Haga público su setter para satisfacer el serializador, pero simplemente no haga nada en el setter. No es "purista" pero lo hace

public string MyProperty 
{ 
    get { 
     return this._myProperty 
    } 
    set {} 
} 
0

Como otros han dicho, WCF necesita getters y setters. Dicho esto, vine aquí con la misma pregunta y las respuestas me hicieron preguntar por qué necesitaba una propiedad de solo lectura. Si utiliza el patrón MVVM, la clase devuelta por el servicio es el Modelo y, por lo tanto, no debe exponerse directamente mediante la IU. Puede hacer fácilmente ViewModel de solo lectura. Alternativamente, podría usar una clase de fachada no dirigida a UI.

3

No se puede hacer que las propiedades de sólo lectura, sin embargo se puede conseguir cerca de sólo lectura haciendo que la parte de su contrato campos en lugar de las propiedades:

[DataContract] 
public class A 
{ 
    public class A(){} 
    public class A(int readonlyproperty){ _readonlyproperty = readonlyproperty} 

    [DataMember(Name = "ReadOnlyProperty")] 
    internal int _readonlyproperty; 

    public int ReadOnlyProperty { 
     get {return _readonlyproperty;} 
     private set {_readonlyproperty = value;} 
} 

próxima que sus partes internas accesable en WCF:

[assembly: InternalsVisibleTo("System.Runtime.Serialization")] 

Algunas muestras de cómo utilizar esto para su ventaja: wcf-and-datacontract-serialization-internals-and-tips

0

en realidad, puede hacer que el de sólo lectura campos serializable.Es necesario establecer la propiedad 'SerializeReadOnlyTypes' de los DataContractSerializerSettings a 'True', cuando se construye DataContractSerializer, como a continuación:

var xmlSerializer = new DataContractSerializer(typeof(yourTypeHere), new DataContractSerializerSettings {SerializeReadOnlyTypes=true}); 

Ver la descripción de MSDN y los detalles, aquí: https://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializersettings(v=vs.110).aspx

0

WCF tiene que poder serializar/deserializar la propiedad, lo que no es posible con una propiedad privada. Para tener una propiedad de sólo lectura (dentro de un tipo complejo):

  • clase decorar como [DataContract (IsReference = true)]
  • decorar cada/la propiedad como [DataMember]
  • Get Pública, interna Establecer
[DataContract(IsReference = true)] 
    public class Format : ValueObject<Format> 
    { 
     [DataMember] 
     public int Height { get; internal set; } 
    } 
Cuestiones relacionadas