2010-04-19 51 views
5

Por lo tanto, actualmente tengo 2 WSDL agregados como referencias de servicio en mi solución. Son similares a esto en mi archivo app.config (He quitado el campo "fijaciones", porque es poco interesante):¿Cambiar dirección/puerto de WSDL EndPointAddress en tiempo de ejecución?

<system.serviceModel> 
    <client> 
    <endpoint address="http://localhost:8080/query-service/jse" binding="basicHttpBinding" bindingConfiguration="QueryBinding" contract="QueryService.Query" name="QueryPort" /> 
    <endpoint address="http://localhost:8080/dataimport-service/jse" binding="basicHttpBinding" bindingConfiguration="DataImportBinding" contract="DataService.DataImport" name="DataImportPort" /> 
    </client> 
</system.serviceModel> 

Cuando utilizo un WSDL, se ve algo como esto:

using (DataService.DataClient dClient = new DataService.DataClient()) 
{ 
    DataService.importTask impt = new DataService.importTask(); 
    impt.String_1 = "someData"; 
    DataService.importResponse imptr = dClient.importTask(impt); 
} 

En la declaración "using", al crear una instancia del objeto DataClient, tengo 5 constructores disponibles para mí. En este escenario, yo uso el constructor por defecto:

new DataService.DataClient() 

que utiliza la Cadena de dirección integrada de punto final, que yo supongo que se extrae de app.config. Pero quiero que el usuario de la aplicación tenga la opción de cambiar este valor.

1) ¿Cuál es la mejor/más fácil forma de obtener programáticamente esta cadena?

2) Entonces, una vez que he permitido que el usuario edite y pruebe el valor, ¿dónde debería almacenarlo?

Prefiero tenerlo almacenado en un lugar (como app.config o equivalente) para que no haya necesidad de verificar si el valor existe o no y si debería estar usando un constructor alternativo. (Buscando mantener mi código ajustado, ¿sabes?)

¿Alguna idea? Sugerencias?

EDITAR

Tal vez debería preguntar acerca de estos constructores alternos también.

Por ejemplo, uno de ellos tiene el siguiente aspecto:

¿Qué valores se van pasando por "endPointConfigurationName" y "RemoteAddress"?

Edit2

responder a mis propias preguntas aquí, el "endPointConfigurationName" parece ser el mismo que el "nombre" en el XML app.config y el "RemoteAddress" se formatea el mismo como "dirección de punto final "en la aplicación.config XML.

También! La respuesta a la primera pregunta acerca de cómo obtener los EndPointAddresses es la siguiente:

ClientSection clSection = 
    ConfigurationManager.GetSection("system.serviceModel/client") as ClientSection; 

ChannelEndpointElementCollection endpointCollection = 
    clSection.ElementInformation.Properties[string.Empty].Value as ChannelEndpointElementCollection; 

Dictionary<string, string> nameAddressDictionary = 
    new Dictionary<string, string>(); 

foreach (ChannelEndpointElement endpointElement in endpointCollection) 
{ 
    nameAddressDictionary.Add(endpointElement.Name, 
          endpointElement.Address.ToString()); 
} 

Edit3

Ok, creo que he descubierto el 2 ° tiempo (y por lo tanto, la solución completa) a mi problema . He encontrado esto en otro sitio web y lo ha modificado para satisfacer mis necesidades:

Configuration configuration; 
ServiceModelSectionGroup serviceModelSectionGroup; 
ClientSection clientSection; 

configuration = 
    ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
serviceModelSectionGroup = 
    ServiceModelSectionGroup.GetSectionGroup(configuration); 
clientSection = serviceModelSectionGroup.Client; 

foreach (ChannelEndpointElement endPt in clientSection.Endpoints) 
{ 
    MessageBox.Show(endPt.Name + " = " + endPt.Address); 
} 
configuration.Save(); 

Con este código, tenemos acceso a los clientSection.Endpoints y puede acceder y cambiar todas las propiedades de los miembros, así como "Dirección". Y luego, cuando hayamos terminado de cambiarlos, podemos hacer configuration.Save() y todos los valores se escriben en un archivo de usuario.

Ahora aquí está el truco.En el modo de depuración, el "configuration.save()" no parece conservar sus valores desde la ejecución hasta la ejecución, pero cuando ejecuta la aplicación normal (fuera del modo de depuración), los valores persisten. (Lo cual es bueno.) Así que esa es la única advertencia.

EDIT4

Hay otra advertencia. Los cambios realizados en los WSDL no tienen efecto durante el tiempo de ejecución. La aplicación tiene que ser reiniciado para releer los valores del archivo de configuración de usuario en la memoria (al parecer.)


La única otra cosa que podría estar interesado en es encontrar una manera (una vez que los valores se han cambiado) para revertir los valores a sus valores predeterminados. Claro, probablemente puedas borrar el archivo de usuario, pero eso borra todas las configuraciones personalizadas.

¿Alguna idea?

EDIT5

estoy pensando inyección de dependencia podría ser perfecto aquí, pero necesitará investigar más ...

EDITAR 6

no tengo privilegios de comentario pero necesita ejecutar

ConfigurationManager.RefreshSection("client"); 

para tener la caché actualizada de modo que los cambios sucedan inmediatamente.

Respuesta

2

Si está utilizando Microsoft Agregue la referencia web para crear su referencia de servicio, entonces creo que puede tener problemas para cambiar la conexión mediante programación. Incluso si cambió el código generado automáticamente, tan pronto como lo hizo, Update Service Reference se sobrescribirá.

Lo mejor es arañar el código generado automáticamente de Microsoft y crear sus propias clases de WCF. No es difícil y ofrece mucha flexibilidad/escalabilidad.

Here's an excellent article sobre este mismo tema.

En cuanto al almacenamiento de las direcciones personalizadas, dependerá de su aplicación si se trata de una aplicación Silverlight, Windows o web. Mi elección personal es la base de datos.

+0

Volveré a leer ese artículo (mis ojos comenzaron a brillar más o menos a la mitad del artículo ...) Pero no estoy de acuerdo: es * bastante * difícil. Sobre todo teniendo en cuenta que apenas sé qué se supone que están haciendo estos WSDL. Y puedo tener hasta 22 WSDL que eventualmente tendré que integrar. "Agregar referencia de servicio" fue una magia maravillosa. Limitador, seguro, pero maravilloso porque hizo que mi proyecto funcionara rápidamente. (Le daré un +1 de todos modos, ya que es un buen hallazgo. Gracias!) – Pretzel

+0

Sí, me doy cuenta de que sueno como un programador perezoso. ¿No somos todos, hasta cierto punto? :-) Te juro que voy a tomar unas cuantas fotos más de esto, pero parece que estoy tratando de obtener un título en Ingeniería Civil y Arquitectura, solo para construir una cabaña en mi patio trasero. ¿Tu sabes? – Pretzel

+0

@Pretzel - ¡Buena pena, 22 referencias! En ese caso, hay una solución rápida y sucia que he usado en el pasado. Intente aprovechar clases parciales. La idea sería tener una clase parcial para los generados automáticamente para que no pierdas tu código en una actualización de referencia de servicio. De cualquier manera, estás en una encrucijada. O aprende y analiza el código generado por Microsoft, o escribe el tuyo. – Matt

Cuestiones relacionadas