Práticas recomendadas do MVVM com o cliente WPF e o serviço duplex WCF

5

Estou pensando em como projetar meu aplicativo WPF, que recebe dados de um serviço duplex WCF, mas tenho medo de engenharia excessiva.

Eu pensei em abstrair a comunicação do WCF completamente do cliente WPF criando uma biblioteca "cliente proxy" que implementa as interfaces de serviço e retorno de chamada internamente.

Dessa forma, não é necessário criar a classe de retorno de chamada no aplicativo WPF, mas assinar eventos no cliente proxy que são chamados quando os métodos de retorno de chamada são chamados pelo serviço. Isso permitiria ocultar a referência de serviço do WPF.

Em seguida, no WPF, tudo o que farei é:

var client = new ApiClient(); //This is the client library
var stuff = client.GetStuff(); //Some service method
client.StuffDeleted += OnStuffDeleted; //Event that is invoked by library on callback

Eu provavelmente instanciaria o cliente apenas uma vez como um objeto Singleton para todos os ViewModels chamarem.

Depois, achei que poderia levar isso adiante criando classes "Model" que são quase idênticas às classes geradas pela referência de serviço WCF (contratos de dados), adicionando outra camada no topo do cliente proxy e usando o automapper para criar meus modelos , em seguida, retornando-os ao WPF em vez de classes de contrato de dados.

Eu imaginei que dessa forma eu conseguiria uma separação completa do meu serviço WCF e ter uma camada extra permitiria que eu adicionasse metadados aos meus modelos antes de retorná-los e, no lado do WPF, usaria esses modelos para construir o ViewModel que é destinado apenas para visualização / ligação.

Ter esse cliente também facilitaria a centralização da lógica de negócios, o tratamento de erros e a simplificação do teste de unidade, já que o cliente WCF é um único componente independente.

O problema é que eu tenho medo de mais de engenharia isso. O banco de dados tem entidades EF, o serviço WCF tem suas próprias classes DTO, então eu teria Modelos e ViewModels. Também notei que as classes geradas pelo WCF implementam a interface INotifyPropertyChanged, o que me faz pensar que elas deveriam ser usadas como modelos (ou para enviar atualizações para o serviço?).

Vou tentar resumir minhas principais perguntas em tópicos:

  • No M-V-VM, é uma boa prática usar as classes generalizadas de referência de serviço como Modelos?
  • Há muito benefício em abstrair completamente o WCF do WPF com um cliente proxy?
    • Os métodos de retorno de chamada chamariam eventos nos quais o WPF está inscrito
  • Por que as classes de referência de serviço geradas implementam INotifyPropertyChanged?

O design é um exagero?

Muito obrigado.

ATUALIZAÇÃO:

Visualização do que estou tentando fazer:

Como pode ser visto, o cliente Proxy no meio tem 2 camadas (classes):

A primeira classe é o que o WPF instancia como Singleton e usa para recuperar as classes do modelo.

A segunda classe é um wrapper em torno do cliente de referência de serviço e é chamado pela primeira camada. Isso é puramente para fins de acesso a dados.

Eu não adicionei os métodos de retorno de chamada que serão eventos que o WPF assina.

    
por Shahin Dohan 07.11.2016 / 22:16
fonte

1 resposta

1

Eu tive uma situação como essa no passado e acabamos criando uma camada separada do Modelo WPF para o aplicativo.

Não sei quanto mudou desde então, mas nossas razões para isso foram:

  • Queríamos propriedades somente leitura no aplicativo, e os DTOs gerados pelos DataContracts tinham que ser de leitura / gravação

  • Algumas classes eram muito grandes, mas o modelo de interface do usuário precisava apenas de uma seção muito menor dos dados.

  • Algumas propriedades na camada da interface do usuário tinham lógica personalizada. Por exemplo, queríamos manter a propriedade db como um int de 123, no entanto, para fins de UI, queríamos uma string "000123"

  • Queremos manter aberta a possibilidade no futuro de alterar a pilha de tecnologia de uma camada, como substituir a camada WCF ou EF por outra alternativa. Ao separá-los, precisaríamos apenas reescrever uma camada em vez de tudo no aplicativo.

  • Queríamos adicionar uma camada de criptografia a alguns dados, para que os dados fossem criptografados em repouso ou para transferência ... Não me lembro muito desse requisito, mas isso contribuiu para nossa decisão.

Nosso resultado final foi:

  • Projeto para modelos do WPF que cria apenas os modelos de interface do usuário usados pelo aplicativo, usando as propriedades, os tipos de dados e o escopo corretos exigidos pela interface do usuário.

  • Projeto para Data Access Layer, que cuidaria da conversão de modelos WPF para modelos DTO ou EF para transferência para camada de banco de dados. Nós realmente usamos o AutoMapper para isso também.

  • O projeto real do WCF, com classes geradas automaticamente a partir do WCF

  • O projeto EF real, com modelos e procedimentos EF gerados automaticamente

Se bem me lembro, da camada de aplicação do WPF, faríamos algo como:

ISomeService service = DAL.SomeService();
ISomeModel stuff = service.GetStuff();

O DAL retornaria uma classe de serviço que atendesse a alguma interface. Se algum dia quisermos substituir a camada de serviço por outra, poderíamos sem afetar o restante do aplicativo WPF.

Além disso, ISomeModel poderia implementar itens específicos para o próprio aplicativo WPF, como lógica ou eventos personalizados. Ele não precisa estar vinculado ao objeto de dados que enviamos / recebemos para o banco de dados.

    
por 08.12.2016 / 17:37
fonte