WCF C # - получение определенных значений конфигурации из App.config - PullRequest
3 голосов
/ 20 июля 2011

У меня есть служба WCF XYZ, которая будет развернута на нескольких хостах.Каждый такой сервис может иметь соединение с другим сервисом XYZ, развернутым на одном из других хостов.Это распределенная система, в которой состояния между службами будут различаться.

Для того, чтобы общаться, для меня не имеет смысла добавлять ссылку на службу в Visual Studio, потому что это просто добавит избыточность (службауже знает, с чем он будет взаимодействовать).

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

<client>
  <endpoint name="BEL" 
            address="tcp://us.test.com:7650/OrderManagementService"
            binding="tcpBinding"
            contract="IOrderManagementService"/>
  <endpoint name="BEL2"
      address="tcp://us.test2.com:7650/OrderManagementService"
      binding="tcpBinding"
      contract="IOrderManagementService"/>
</client>

Теперь я просто хочу прочитать эти настройки и создать ChannelFactories и Channels в моем коде.Тем не менее, это становится проблемой, чтобы сделать это.

Два вопроса: я делаю вещи правильно;и если да, то каков наилучший способ извлечь эти значения из файла конфигурации?

Ответы [ 4 ]

3 голосов
/ 20 июля 2011

Создание каналов напрямую не сложно, и вся конфигурация конечной точки читается для вас.Попробуйте что-то вроде этого:

var factory = new ChannelFactory<IOrderManagementService>("BEL");
var proxy = factory.CreateChannel();
// call methods on proxy
proxy.Close();

Обратите внимание, что прокси-сервер должен закрываться правильно (что означает правильный вызов Close или Abort), как только вы закончите с ним.Однако вы можете оставить фабрику открытой на длительное время, даже в кеше.

Вы можете инкапсулировать это в вспомогательные методы, чтобы сделать вызывающий код простым:

public static ChannelFactory<TContract> NewChannelFactory<TContract>(string endpointConfigurationName) where TContract : class {
    // TODO: Cache the factory in here for better performance.
    return new ChannelFactory<TContract>(endpointConfigurationName);
}

public static void Invoke<TContract>(ChannelFactory<TContract> factory, Action<TContract> action) where TContract : class {
    var proxy = (IClientChannel) factory.CreateChannel();
    bool success = false;
    try {
        action((TContract) proxy);
        proxy.Close();
        success = true;
    } finally {
        if(!success) {
            proxy.Abort();
        }
    }
}
0 голосов
/ 20 июля 2011

Поскольку все ваши подключения имеют один и тот же контракт и, по сути, один и тот же клиентский код, вы можете использовать один и тот же ChannelFactory, чтобы создать столько ServiceChannel s, сколько вам нужно, и вы можете подключить каждый ServiceChannel к разным EndpointAddress как указано в обычных настройках старого приложения или в базе данных:

private List<string> _endpointLists = new List<string>() { "127.0.0.0:1234" };
private static ChannelFactory<IWCFServiceChannel> _channelFactory = new ChannelFactory<ServiceReference.IWCFServiceChannel>("App.config Binding Name Here");
private List<WCFServiceChannel> _serviceChannels = new List<WCFServiceChannel>();

foreach (string uriEndpoint in _endpointLists)
    _serviceChannels.Add(_channelFactory.CreateChannel(new EndpointAddress(uriEndpoint)));

_serviceChannels[0].Open();
...

И вы можете делать это столько раз, сколько вам нужно, используя тот же ChannelFactory, но создавая новый ServiceChannel s с разными конечными точками каждый раз.

0 голосов
/ 20 июля 2011

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

    public DspServiceMediator( String serviceAddress)
    {
        EndpointAddress end_point = new EndpointAddress(serviceAddress);
        NetTcpBinding new_tcp = new NetTcpBinding(SecurityMode.None);
        new_tcp.ReceiveTimeout = TimeSpan.MaxValue;
        new_tcp.SendTimeout = new TimeSpan(0, 0, 30); //30 seconds
        //_channelFactory = new ChannelFactory<DspServiceClient>(new_tcp, end_point);
        _dspClient = new DspServiceClient(new_tcp, end_point);
    }

Я на самом деле реплицировал каждое свойство в сервисе (много раз у меня были маленькие моды, которые делали сервис проще в использованииконечный клиент), но вы можете просто нарушить закон Demeter в своем клиентском коде и вернуть базовый клиент службы (_dspClient в приведенном выше коде) и использовать его.

0 голосов
/ 20 июля 2011

WebConfigurationManager может использоваться для получения ваших конечных точек.У вас есть клиентский раздел, поэтому в GetSection просто пропустите его, как показано выше.

ClientSection clientSection = (WebConfigurationManager.GetSection("system.serviceModel/client") as ClientSection);

foreach(ChannelEndpointElement cee in clientSection.Endpoints)
{
    // Store your endpoint for future use with ChannelFactories 
}
...