Pergunta

Eu tenho uma classe do lado do servidor que faço disponíveis no lado do cliente através de um [DataContract]. Essa classe tem um campo somente leitura que eu gostaria de colocar à disposição através de uma propriedade. No entanto, eu sou incapaz de fazê-lo porque não parece que eu estou autorizado a adicionar um [DataMember] propriedade sem ter ambos get e set.

Assim - há uma maneira de ter um [DataMember] propriedade sem setter?

[DataContract]
class SomeClass
{
    private readonly int _id; 

    public SomeClass() { .. }

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

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

Ou a solução ser a utilização [DataMember] como o campo - (como por exemplo mostrado aqui )? fazendo tentei isso também, mas ele não parece se importar o campo é somente leitura ..?

Editar : É a única maneira de fazer uma propriedade somente leitura cortando assim? (Não - eu não quero fazer isso ...)

[DataMember]
public int Id
{
    get { return _id; }
    private set { /* NOOP */ }
}
Foi útil?

Solução

Sua classe "server-side" não será "disponibilizado" para o cliente, realmente.

O que acontece é o seguinte: com base no contrato de dados, o cliente irá criar uma nova classe separada do esquema XML do serviço. É não pode usar a classe do lado do servidor, por si só!

Ele vai recriar uma nova classe a partir da definição de esquema XML, mas esse esquema não contém nenhuma das coisas .NET específicos como de visibilidade ou acesso modificadores - é apenas um esquema XML, depois de tudo. A classe do lado do cliente irá ser criado de forma tal que ele tem a mesma "pegada" no fio - e.g. ele serializa no mesmo formato XML, basicamente.

Você não pode "transporte" .NET específico know-how sobre a classe através de um serviço baseado em SOAP padrão - afinal, tudo o que você está passando ao redor são mensagens serializados - sem aulas

Verifique as "Quatro princípios de SOA" (definido por Don Box da Microsoft):

  1. Os limites são explícitos
  2. Serviços são autônomos
  3. Serviços esquema compartilhar e contrato, não a classe
  4. Compatibilidade é baseada em política

Ver ponto # 3 - serviços esquema compartilhar e contrato, não classe - você só compartilhar o esquema de interface e XML para o contrato de dados - isso é tudo -. Sem classes .NET

Outras dicas

colocar DataMember atributo em um campo não a propriedade.

Lembre-se de pensamento, que WCF não sabe encapsulamento. Encapsulamento é um termo OOP, não é um termo SOA.

Dito isso, lembre-se que o campo será somente leitura para pessoas que usam sua classe -. Qualquer um que usa o serviço terá acesso total ao campo do lado deles

Eu tive algumas propriedades em uma classe em minha camada de serviço que eu queria passar para Silverlight. Eu não quero criar uma classe totalmente nova.

Não é verdade 'recomendado', mas este parecia o menor de dois males para passar sobre a propriedade Total para o Silverlight (apenas para ligação de dados visual).

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");
        }
    }
}

Existe uma maneira de conseguir isso. Mas esteja avisado que viola diretamente o seguinte princípio citado em esta resposta :

"3. Serviços esquema compartilhar e contrato, não de classe."

Se esta violação não lhe diz respeito, este é o que você faz:

  1. Mover os contratos de serviços e de dados em uma biblioteca de classe separada (portátil). (. Vamos chamada esta SomeService.Contracts montagem) Isto é como você definir uma classe [DataContract] imutável:

    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;
        }
    }
    

    Note que [DataMember] é aplicada ao campo de apoio, e não para a propriedade só de leitura correspondente.

  2. Referência do contrato de montagem de ambos seu projeto aplicativo de serviço (vou chamar meus SomeService.Web) e de seus projetos de clientes (o meu é chamado SomeService.Client). Isso pode resultar nos seguintes dependências do projeto dentro de sua solução:

    Captura de tela destacando as dependências do projeto em Solution Explorer

  3. Em seguida, quando você adicionar a referência de serviço para o seu projeto de cliente, certifique-se de ter a opção "Tipos de reutilização" habilitado, e garantir que o seu contrato de montagem (SomeService.Contracts) será incluído no seguinte:

    Captura de tela destacando a configuração de referência de serviço relevante

Voilà! Visual Studio, em vez de gerar um novo tipo Foo do esquema WSDL do serviço, vai reutilizar o tipo Foo imutável do seu contrato de montagem.

Um último aviso: Você já se desviou do serviço princípios citados na que outra resposta . Mas tente não se afastar ainda mais. Você pode ser tentado a começar a adicionar (negócio) lógica para suas classes de contrato de dados; não. Eles devem ficar o mais perto de objetos de transferência de dados mudos (DTOs) como você pode gerenciar.

Definir o contrato de serviço (Interface) Antes de implementar o contrato de uso da classe.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top