1

我的应用程序在运行时更改端点设置并将更改保存到配置文件。但是当我创建一个新的服务代理实例时,端点设置是更新之前的设置。如何强制代理获取新设置?

4

1 回答 1

3

您将需要检测您的配置文件是否已更新,无论是您的主 app.config / web.config 还是您通过 configSource 使用的任何外部配置文件。

如果检测到更改,您将需要刷新 system.serviceModel 配置部分:

ConfigurationManager.RefreshSection("system.serviceModel/client");

现有的Channels并且ChannelFactories不会接受更改,因此需要关闭它们并创建新的。

以下示例显示了这一点:

[TestFixture]
class When_trying_to_change_service_endpoints_on_the_fly
{
    [Test]
    public void Should_use_the_new_endpoint()
    {
        var someService1 = Substitute.For<ISomeWebService>();
        var someService2 = Substitute.For<ISomeWebService>();

        var serviceHost1 = CreateServiceHost(someService1, new Uri("http://localhost:50001"));
        var serviceHost2 = CreateServiceHost(someService2, new Uri("http://localhost:50002"));

        serviceHost1.Open();
        serviceHost2.Open();

        UpdateEndpointInConfig(new Uri("http://localhost:50001"));

        var channelFactory = new ChannelFactory<ISomeWebService>("TestReloadConfig");

        var channel1 = channelFactory.CreateChannel();
        channel1.ServiceMethod();
        ((IChannel)channel1).Close();

        channelFactory.Close();

        UpdateEndpointInConfig(new Uri("http://localhost:50002"));

        channelFactory = new ChannelFactory<ISomeWebService>("TestReloadConfig");

        var channel2 = channelFactory.CreateChannel();
        channel2.ServiceMethod();
        ((IChannel)channel2).Close();

        serviceHost1.Close();
        serviceHost2.Close();

        someService1.Received(1).ServiceMethod();
        someService2.Received(1).ServiceMethod();
    }

    private static void UpdateEndpointInConfig(Uri endpointAddress)
    {
        var configFile = new ExeConfigurationFileMap();
        configFile.ExeConfigFilename = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath;

        var config = ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);

        var serviceModelConfig = (ServiceModelSectionGroup) config.GetSectionGroup("system.serviceModel");
        serviceModelConfig.Client.Endpoints[0].Address = endpointAddress;

        config.Save();

        ConfigurationManager.RefreshSection("system.serviceModel/client");
    }

    private ServiceHost CreateServiceHost<TService>(TService service, Uri baseUri)
    {
        var serviceHost = new ServiceHost(service, new Uri[0]);

        serviceHost.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
        serviceHost.Description.Behaviors.Find<ServiceBehaviorAttribute>().InstanceContextMode = InstanceContextMode.Single;

        serviceHost.AddServiceEndpoint(typeof(TService), new BasicHttpBinding(), baseUri);

        return serviceHost;
    }
}

[ServiceContract]
public interface ISomeWebService
{
    [OperationContract]
    void ServiceMethod();
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <client>
      <endpoint address="http://localhost:50000" binding="basicHttpBinding" contract="Junk.ISomeWebService" name="TestReloadConfig" />
    </client>
  </system.serviceModel>
</configuration>

如果您以另一种方式管理端点配置,您可以ChannelFactory手动更新任何实例,因为您可以访问 Endpoint 和 Binding 属性。

于 2013-10-14T16:06:54.743 回答