2009-12-11 13 views
6

Tengo una aplicación WPF que hasta ahora solo ha sido cliente, pero ahora estoy trabajando en dividirla en un lado del cliente y del servidor. En este trabajo, presentaré WCF para la comunicación cliente-servidor. Mi aplicación tiene varios proyectos y se necesitan referencias de servicio de más de uno de ellos.Estructura de la aplicación usando WCF

El esfuerzo inicial para hacer la separación es hacer todo "directo". Todos los proyectos que necesitan comunicarse con un servicio obtienen una referencia de servicio, al igual que el proyecto principal de la aplicación WPF: para obtener allí la aplicación .config. Encuentro que esto se convierte en un desastre bastante rápido, y no puedo imaginar que esta sea la arquitectura típica que usa la gente. También he visto problemas con el hecho de que cada una de las referencias de servicio genera una nueva implementación de las clases de DataContract; por lo tanto, no existe una comprensión común de las clases DataContract en el cruce de proyectos. Tengo algunas clases de ViewModel en un proyecto y otro proyecto que instancia cierto ViewModel. Me gustaría pasar el objeto recibido del servicio, pero no puedo, ya que la representación del objeto recibido generada por el cliente difiere en cada proyecto.

Entonces, ¿hay una forma recomendada de estructurar tales separaciones de cliente/servidor utilizando WCF? O principios a seguir? Estoy pensando en un proyecto Proxy común utilizado en el lado del cliente que hace la comunicación con los servicios, envuelve los datos recibidos y devuelve datos en un formulario bien conocido por las bibliotecas del cliente. ¿Debería dar solo una referencia de servicio, y supongo que solo necesito App.config en el proyecto wpfApp? ¿Esto tiene sentido?

Respuesta

16

me gusta estructurar mis soluciones WCF como esto:

contratos (biblioteca de clases)
contiene todos los contratos de servicio, operaciones, fallas, y de datos.Puede ser compartido entre el servidor y el cliente en un escenario pura-NET-NET a

aplicación Servicio (biblioteca de clases)
contiene el código para implementar los servicios, y los métodos de soporte/cooperadoras necesarias para lograr este . Nada más.

host (s) de servicio (opcional - puede ser Winforms, aplicación de consola, NT Service)
Contiene host de servicio (s) para la depuración/pruebas, o posiblemente también para la producción.

Esto básicamente me da el lado del servidor de las cosas.

En el lado del cliente:

proxies cliente (biblioteca de clases)
me gusta para empaquetar mis servidores proxy cliente en una biblioteca de clases por separado, de modo que puedan ser reutilizados por múltiples aplicaciones reales de los clientes. Esto se puede hacer usando svcutil o "Agregar referencia de servicio" y ajustando manualmente los horribles app.config resultantes, o haciendo la implementación manual de proxies de cliente (cuando se comparte el ensamblado de contratos) utilizando construcciones ClientBase<T> o ChannelFactory<T>.

1-n clientes, actuales (cualquier tipo de aplicación)
típicamente única referencia del conjunto de servidores proxy cliente, o tal vez el conjunto de contratos, también, si está siendo compartida. Esto puede ser ASP.NET, WPF, Winforms, aplicación de consola, otros servicios, lo que sea.

De esa manera; Tengo un diseño agradable y limpio, lo uso constantemente una y otra vez, y realmente creo que esto ha hecho que mi código sea más limpio y fácil de mantener.

Esto se inspiró en el Extreme WCF screen cast de Miguel Castro en DotNet Rocks TV con Carl Franklin - elenco de pantalla muy recomendable!

+0

Gracias por una muy buena respuesta!Algunas preguntas atrás: ¿Al contar con un servidor de servicio, debe iniciar el host y el cliente al iniciar su aplicación? ¿O hay alguna forma de evitar esto? Con respecto a los poderes del cliente, ¿cuál preferirías? La impl manual suena más consistente, ya que no tiene que ocuparse de las referencias de servicio que están desactualizadas. – stiank81

+0

@bambuska: seguro, debe iniciar el servidor de servicio y el cliente para probar; seleccione "lanzar proyectos múltiples" en Visual Studio para lograr esto: puede ejecutar tanto el host de servicio como el cliente al presionar F5. –

+1

Proxies de cliente: me gusta el control total que tengo cuando realizo la implementación manual de los proxies del cliente; esto ** requiere ** aunque puedo compartir el contrato entre el servidor y el cliente (ya que la implementación manual de los proxies del cliente debe tener acceso a los contratos reales) –

1

Depende. WCF es un gran marco y está diseñado para abarcar una gran cantidad de escenarios diferentes.

Sin embargo, para una aplicación directa como la suya, cuando no se preocupan cosas como Java interoperabilidad de interoperabilidad o servicios web genéricos, esto es lo que hago:

Todas las clases e interfaces DataContract ServiceContract entrar en una biblioteca (o bibliotecas) que se comparte entre el cliente y el servidor. Tenga en cuenta que probablemente no debería decorar la implementación de su servicio con ServiceContract, crearía una interfaz separada con los atributos de ServiceContract que podría colocar en un ensamblado compartido.

Así que parece que estás haciendo casi todo bien. Lo que probablemente NO se necesita es generar automáticamente los proxies en este caso. Eso solo te está causando dolor. Por lo tanto, no use el cuadro de diálogo Agregar referencia de servicio para lo que está haciendo. Simplemente incluya sus ensamblados de DataContract compartidos y use ChannelFactory para obtener un proxy para su interfaz de servicio definida en la biblioteca compartida. Esto también evita tener que volver a generar el proxy en Visual Studio, que, para cualquier proyecto de tamaño decente, se vuelve MUY RÁPIDO.

Si va por esta ruta, también puede deshacerse del punto final MetaDataExchange, ya que eso solo es necesario para describir el servicio al cliente. Como hace todo en un ensamblado compartido, no necesita la descripción del servicio, ya que ya tiene la descripción del servicio en forma de código.

+0

Gracias! Esto suena muy atractivo. Los proxies generados automáticamente ya han causado dolor ... En realidad estoy intentando una implementación similar a la que ya describes, pero se detuvo cuando quise los servicios asincrónicos. ¿Puedo usar fácilmente ChannelFactory para generar servicios asíncronos también? – stiank81

+0

Ah, y JavaInterop, etc. no es relevante en absoluto. ¡Esto será todo .net a .net! Al tener los DataContracts en una biblioteca compartida, en realidad puedo devolver, p. un objeto MyClass de un servicio, y será exactamente el mismo tipo recibido? – stiank81

+0

Sí: http://msdn.microsoft.com/en-us/library/bb885132.aspx –

1

La estructura habitual que utilizo es:

común - contiene interfaces, ficha contratos, contratos de servicios, clases abstractas, etc; Cliente - referencias Común, contiene la clase proxy del servidor; Servidor - referencias Común, contiene clases de implementación reales;

+1

De acuerdo. Aunque a menudo haré que la biblioteca común incluya DTO que se puedan usar en ambos lados del servicio y luego no use las clases proxy generadas. – asgerhallas

+0

¡Parece que necesito tener un proyecto común para las cosas compartidas ...! ¿Está utilizando proxies autogenerados u omitiendo aquellos, como @asgerhallas? Claro que creo que me gustaría omitir su uso si puedo. Ya han causado demasiado dolor. – stiank81

+1

Derivo la clase proxy de ClientBase e implemento la interfaz para reenviar llamadas al canal. – Goran

Cuestiones relacionadas