WCF ChannelFactory vs generación de proxy

82

¿Solo me preguntaba en qué circunstancias preferiría generar un proxy desde un servicio WCF cuando puede invocar llamadas usando ChannelFactory?

¿De esta manera no tendrá que generar un proxy y preocuparse por regenerar un proxy cuando se actualice el servidor?

Gracias

TheWommies
fuente
Utilice siempre ChannelFactory. No puedo afirmar esto con suficiente fuerza.
tom redfern

Respuestas:

88

Hay 3 formas básicas de crear un cliente WCF:

  1. Deje que Visual Studio genere su proxy. Este auto genera código que se conecta al servicio leyendo el WSDL. Si el servicio cambia por algún motivo, debe volver a generarlo. La gran ventaja de esto es que es fácil de configurar: VS tiene un asistente y todo es automático. La desventaja es que dependes de VS para que haga todo el trabajo duro por ti, por lo que pierdes el control.

  2. Úselo ChannelFactorycon una interfaz conocida. Esto depende de que tenga interfaces locales que describen el servicio (el contrato de servicio). La gran ventaja es que puede administrar los cambios mucho más fácilmente: aún tiene que volver a compilar y corregir los cambios, pero ahora no está regenerando código, está haciendo referencia a las nuevas interfaces. Por lo general, esto se usa cuando controla tanto el servidor como el cliente, ya que ambos pueden burlarse mucho más fácilmente para las pruebas unitarias. Sin embargo, las interfaces se pueden escribir para cualquier servicio, incluso REST; eche un vistazo a esta API de Twitter .

  3. Escriba su propio proxy: esto es bastante fácil de hacer, especialmente para los servicios REST, usando HttpCliento WebClient. Esto le brinda el control de grano más fino, pero a costa de muchas API de servicio en cadenas. Por ejemplo: var content = new HttpClient().Get("http://yoursite.com/resource/id").Content;- si los detalles de la API cambian, no encontrará un error hasta el tiempo de ejecución.

Personalmente, nunca me ha gustado la opción 1: confiar en el código generado automáticamente es complicado y pierde demasiado control. Además, a menudo crea problemas de serialización: termino con dos clases idénticas (una en el código del servidor, una generada automáticamente) que se pueden mejorar pero es una molestia.

La opción 2 debería ser perfecta, pero los canales son demasiado limitantes; por ejemplo, pierden por completo el contenido de los errores HTTP . Dicho esto, tener interfaces que describen el servicio es mucho más fácil de codificar y mantener.

Keith
fuente
4
@MurHaf Nope: esta respuesta es completamente mi propio trabajo. SIEMPRE atribuyo las contribuciones de los demás. Escribí esta respuesta basándome en años de trabajo con servicios SOAP en .Net en varios trabajos. Ese artículo al que enlazas es de marzo de 2013, mientras que mi respuesta fue escrita en abril de 2010, ¡3 años antes! Si ha ocurrido plagio, me copió. Debe verificar las fechas antes de hacer acusaciones, ya que es muy fácil de hacer.
Keith
@MurHaf ni siquiera llegamos a las mismas conclusiones: ese artículo recomienda la generación automática de un proxy (opción 1) como 'simple'. Lo describo como fácil de configurar, pero complicado y difícil de mantener. Ni siquiera habla de escribir su propio proxy (opción 3).
Keith
1
Creo que también debería mencionarse SvcUtil, ya que esta es una de las formas más comunes de "escribir" un cliente.
Mare Infinitus
21

Utilizo ChannelFactory junto con el método MetadataResolver.Resolve. La configuración del cliente es una molestia, así que obtengo mi ServiceEndpoint del servidor.

Cuando usa ChannelFactory (Of T), T es el contrato original que puede obtener de una referencia en su proyecto o una instancia de contrato generada. En algunos proyectos, generé el código a partir de una referencia de servicio porque no pude agregar una referencia a la dll del contrato. Incluso puede generar un contrato asincrónico con la referencia de servicio y usar esa interfaz de contrato con ChannelFactory.

El punto principal de usar ChannelFactory para mí fue deshacerme de la información de configuración del cliente WCF. En el código de muestra a continuación, puede ver cómo lograr un cliente WCF sin config.

Dim fixedAddress = "net.tcp://server/service.svc/mex"
Dim availableBindings = MetadataResolver.Resolve(GetType(ContractAssembly.IContractName), New EndpointAddress(fixedAddress))
factoryService = New ChannelFactory(Of ContractAssembly.IContractName)(availableBindings(0))
accesService = factoryService.CreateChannel()

En mi proyecto final, los enlaces disponibles están marcados para usar net.tcp o net.pipe si están disponibles. De esa manera, puedo utilizar la mejor encuadernación disponible para mis necesidades. Solo confío en el hecho de que existe un punto final de metadatos en el servidor.

espero que esto ayude

Por cierto, esto se hace usando .NET 3.5. Sin embargo, también funciona con 4.0.

Jean-Michel Bezeau
fuente
Cosas geniales. También uso MetadataResolver.Resolve para la configuración, pero no pensé en resolver el enlace desde el servidor. ¡Muy buen punto!
Sleeper Smith
voto a favor por mencionarThe main point of using ChannelFactory to get rid of the WCF client config
Kurubaran
11

Bueno, para poder utilizarlo ChannelFactory<T>debes estar dispuesto a compartir montajes contractuales entre el servicio y el cliente. Si esto le parece bien, ChannelFactory<T>puede ahorrarle algo de tiempo.

Andrew Hare
fuente
@Charles: ¿puedes explicar por qué esto no es cierto?
Aran Mulholland
6
@Aran: Creo que lo que Andrew quiere decir es correcto: que si no desea generar facsímiles de las clases de contrato, entonces deberá tener acceso a los originales. Es cierto que de una forma u otra necesitas tener esas clases de contrato. Puede generarlos, escribirlos a mano u obtener el código fuente del servicio (si está en el mismo idioma). Compartir ensamblados es la forma más sencilla, pero no siempre es posible. (Quizás estoy tomando a Andrew demasiado literalmente, pero la claridad es importante aquí.)
Igby Largeman
2
@Charles ok, entonces estás diciendo que podrías usar ChannelFactory <T> incluso si no tuvieras acceso a los ensamblajes codificando a mano la interfaz de T y luego usándolo.
Aran Mulholland
1
@Aran: sí, ya sea mediante codificación manual o mediante el uso de una herramienta como svcutil (asumiendo que el servicio se está ejecutando y es accesible).
Igby Largeman
9

El proxy creará funciones asíncronas para lo cual es agradable.

Aaron Fischer
fuente
2
sí, al mismo tiempo, tanto "Agregar referencia de servicio" de Visual Studio como svcutil.exe en la línea de comandos destruyen su configuración más allá del reconocimiento ... al menos con svcutil.exe, puede definir un modificador "/ noconfig" .....
marc_s
1
ChannelFactory también proporciona métodos asíncronos: msdn.microsoft.com/en-us/library/ms731177.aspx Pero prefiero usar una plantilla T4 para crear una clase asíncrona usando ThreadPool que invocará métodos síncronos.
SandRock
1
Como actualización: con .NET 4.5, ChannelFactory <T> también admite funciones asíncronas basadas en tareas.
gimpf
8

Mi respuesta es una especie de resumen de las respuestas de Keith y Andrew Hare .

Si no controla el servidor, pero solo tiene WSDL / URL, genere un proxy mediante Visual Studio o svcutil. (Tenga en cuenta que Visual Studio a veces falla, cuando svcutil funciona mejor).

Cuando controle tanto el servidor como el cliente, comparta interfaces / contratos y llame a ChannelFactory
.

Michael Freidgeim
fuente
2

No es solo cuestión de ahorrar tiempo. Usar el proxy generado por WSDL es peligroso porque si olvida actualizar la referencia del servicio, puede dejar la solución en un estado inconsistente. Todo se compila pero el contrato de servicio está roto. Definitivamente sugiero usar un ChannelFactory siempre que sea posible, le hace la vida mucho más fácil.

Una posible alternativa podría ser escribir un script previo a la compilación que llame a la utilidad SVCUtil para crear el proxy cada vez que construya su proyecto, pero de todos modos ChannelFactory es mucho más ordenado y elegante.

Paolo Costa
fuente