Изменить адрес / порт WSDL EndPointAddress во время выполнения? - PullRequest
5 голосов
/ 20 апреля 2010

Таким образом, в настоящее время в моем решении добавлено 2 WSDL в качестве ссылок на услуги. Они выглядят так в моем файле app.config (я удалил поле «bindings», потому что это неинтересно):

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

Когда я использую WSDL, это выглядит примерно так:

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

В выражении "using" при создании экземпляра объекта DataClient у меня есть 5 доступных конструкторов. В этом сценарии я использую конструктор по умолчанию:

   new DataService.DataClient()

, который использует встроенную строку адреса конечной точки, которая, как я полагаю, извлечена из app.config. Но я хочу, чтобы у пользователя приложения была возможность изменить это значение.

1) Какой самый лучший / простой способ программного получения этой строки?

2) Тогда, как только я разрешу пользователю редактировать и проверять значение, где мне его хранить?

Я бы предпочел, чтобы оно хранилось в каком-либо месте (например, app.config или эквивалентном), чтобы не было необходимости проверять, существует ли значение или нет, и следует ли мне использовать альтернативный конструктор. (Хочешь держать мой код в узде, понимаешь?)

Есть идеи? Предложения?

EDIT

Может быть, мне стоит спросить и об этих альтернативных конструкторах.

Например, один из них выглядит так:

   new DataService.DataClient(string endPointConfigurationName, 
                              string remoteAddress)

Какие значения могут быть переданы для "endPointConfigurationName" и "remoteAddress"?

EDIT2

Отвечая на мои собственные вопросы, «endPointConfigurationName» выглядит так же, как «name» в XML-файле app.config, а «remoteAddress» форматируется так же, как «адрес конечной точки» в XML-файле app.config.

Также! Ответ на мой первый вопрос о получении EndPointAddresses следующий:

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

Хорошо, я думаю, что я выяснил 2-ую половину (и, таким образом, полное решение) моей проблемы. Я нашел это на другом сайте, и я изменил его, чтобы удовлетворить мои потребности:

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();

С помощью этого кода у нас есть доступ к clientSection.Endpoints и мы можем получить доступ и изменить все свойства элемента, такие как «Адрес». И затем, когда мы закончим их изменение, мы можем выполнить конфигурацию. Save () и все значения записываются в пользовательский файл.

Теперь вот подвох. В режиме отладки «configuration.save ()» не сохраняет ваши значения от исполнения к выполнению, но при нормальном запуске приложения (вне режима отладки) значения сохраняются. (Это хорошо.) Так что это единственное предостережение.

EDIT4

Есть еще одна оговорка. Изменения, внесенные в WSDL, не вступают в силу во время выполнения. Приложение необходимо перезапустить, чтобы перечитать значения файла конфигурации пользователя в память (по-видимому.)


Единственное, что меня может заинтересовать, - это найти способ (после изменения значений) вернуть значения по умолчанию. Конечно, вы можете удалить пользовательский файл, но при этом удаляются все пользовательские настройки.

Есть идеи?

EDIT5

Я думаю, что инъекция зависимости может быть идеальной здесь, но нужно исследовать это подробнее ...

РЕДАКТИРОВАТЬ 6

У меня нет прав на комментарии, но вам нужно запустить

ConfigurationManager.RefreshSection("client");

обновить кэш, чтобы изменения произошли немедленно.

1 Ответ

2 голосов
/ 20 апреля 2010

Если вы используете Microsoft Добавить веб-ссылку , чтобы создать ссылку на службу, то, я думаю, у вас могут возникнуть проблемы с программным изменением соединения. Даже если вы изменили автоматически сгенерированный код, как только вы сделаете Справочник службы обновлений , он будет перезаписан.

Лучше всего - поцарапать автоматически сгенерированный код Microsoft и создать свои собственные классы WCF. Это не сложно, и предлагает большую гибкость / масштабируемость.

Вот отличная статья на эту тему.

Что касается хранения пользовательских адресов, это будет зависеть от вашего приложения, будь то Silverlight, Windows или веб-приложение. Мой личный выбор - база данных.

...