WCF: Exponiendo las propiedades de readonly DataMember sin set?


Tengo una clase del lado del servidor que pongo a disposición en el lado del cliente a través de un [DataContract]. Esta clase tiene un campo de solo lectura que me gustaría poner a disposición a través de una propiedad. Sin embargo, no puedo hacerlo porque no parece que se me permita agregar una propiedad [DataMember] sin tener tanto get como set.

Entonces, ¿hay una manera de tener una propiedad [DataMember] sin setter?

[DataContract]
class SomeClass
{
    private readonly int _id; 

    public SomeClass() { .. }

    [DataMember]
    public int Id { get { return _id; } }        

    [DataMember]
    public string SomeString { get; set; }
}

O será la solución utilizar el [DataMember] como el campo - (como por ejemplo se muestra aquí)? Intenté hacer esto también, pero no parece importarle que el campo sea leído solamente..?

Edit: ¿Es la única manera de hacer una propiedad de readonly pirateándola de esta manera? (no - no quiero hacer esto...)

[DataMember]
public int Id
{
    get { return _id; }
    private set { /* NOOP */ }
}
Author: Community, 2009-12-09

5 answers

Su clase "del lado del servidor" no estará "disponible" para el cliente, realmente.

Lo que sucede es esto: basado en el contrato de datos, el cliente creará una nueva clase separada del esquema XML del servicio. It no puede usar la clase del lado del servidor per se!

Volverá a crear una nueva clase a partir de la definición del esquema XML, pero ese esquema no contiene ninguno de los elementos específicos de.NET, como los modificadores de visibilidad o acceso; después de todo, es solo un esquema XML. El la clase del lado del cliente se creará de tal manera que tenga la misma "huella" en el cable, por ejemplo, se serializa en el mismo formato XML, básicamente.

Usted no puede "transportar" conocimientos específicos de. NET sobre la clase a través de un servicio estándar basado en SOAP-después de todo, todo lo que está pasando son mensajes serializados - ¡sin clases!

Marque los "Cuatro principios de SOA" (definidos por Don Box de Microsoft):

  1. Los límites son explicit
  2. Los servicios son autónomos
  3. Los servicios comparten esquema y contrato, no clase
  4. La compabilidad se basa en la política

Consulte el punto #3 - servicios comparten esquema y contrato, no clase - solo se comparte la interfaz y el esquema XML para el contrato de datos - eso es todo - no clases.NET.

 49
Author: marc_s,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-09 13:30:55

Ponga el atributo DataMember en un campo que no sea la propiedad.

Recuerde pensamiento, que WCF no sabe encapsulación. Encapsulación es un término OOP, no un término SOA.

Dicho esto, recuerde que el campo solo se leerá a las personas que usen su clase - cualquiera que use el servicio tendrá acceso completo al campo de su lado.

 10
Author: Krzysztof Kozmic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-09 13:11:06

Tenía algunas propiedades en una clase en mi capa de servicio que quería pasar a Silverlight. No quería crear una nueva clase.

No realmente 'recomendado', pero este parecía el menor de los dos males para pasar por encima de la propiedad Total a silverlight (únicamente para el enlace visual de datos).

public class PricingSummary
{
    public int TotalItemCount { get; set; } // doesnt ideally belong here but used by top bar when out of store area

    public decimal SubTotal { get; set; }
    public decimal? Taxes { get; set; }
    public decimal Discount { get; set; }
    public decimal? ShippingTotal { get; set; }
    public decimal Total
    {
        get
        {
            return + SubTotal
                   + (ShippingTotal ?? 0)
                   + (Taxes ?? 0)
                   - Discount;
        }
        set
        {
            throw new ApplicationException("Cannot be set");
        }
    }
}
 7
Author: Simon_Weaver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-07 05:26:12

Hay una manera de lograr esto. Pero tenga en cuenta que viola directamente el siguiente principio citado en esta respuesta :

"3. Los servicios comparten esquema y contrato, no clase."

Si esta violación no te concierne, esto es lo que haces:{[12]]}

  1. Mueva los contratos de servicio y datos a una biblioteca de clases separada (portátil). (Llamemos a esta asamblea SomeService.Contracts.) Así es como definirías un [DataContract] clase:

    namespace SomeService.Contracts
    {
        [DataContract]
        public sealed class Foo
        {
            public Foo(int x)
            {
                this.x = x;
            }
    
            public int X
            {
                get
                {
                    return x;
                }
            }
    
            [DataMember]  // NB: applied to the backing field, not to the property!
            private readonly int x;
        }
    }
    

    Tenga en cuenta que [DataMember] se aplica al campo de respaldo, y no a la propiedad de solo lectura correspondiente.

  2. Haga referencia al ensamblaje del contrato tanto de su proyecto de aplicación de servicio (llamaré al mío SomeService.Web) como de sus proyectos cliente (el mío se llama SomeService.Client). Esto podría resultar en las siguientes dependencias del proyecto dentro de su solución:

    captura de pantalla que resalta las dependencias del proyecto en el Explorador de soluciones

  3. A continuación, cuando agregue la referencia de servicio a su cliente proyecto, asegúrese de tener la opción "tipos de reutilización" habilitada, y asegúrese de que su ensamblaje de contrato (SomeService.Contracts) se incluirá en esto:

    captura de pantalla que resalta la configuración de referencia de servicio relevante

Voilà! Visual Studio, en lugar de generar un nuevo tipo Foo a partir del esquema WSDL del servicio, reutilizará el tipo Foo inmutable de su ensamblaje de contrato.

Una última advertencia: Ya se ha desviado de los principios de servicio citados en esa otra respuesta . Pero trata de no alejarte más. Usted podría sentirse tentado a comenzar a agregar lógica (de negocios) a sus clases de contrato de datos; no lo haga. Deben mantenerse lo más cerca posible de los objetos de transferencia de datos (DTO) tontos que pueda administrar.

 6
Author: stakx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:30:01

Definir el contrato de servicio (Interfaz) Antes de implementar el contrato utilizando la clase.

 -3
Author: solairaja,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-09 13:08:05