Может ли несколько служб WCF использовать общий BaseAddress?

У меня есть сборка, содержащая несколько служб WCF, каждая со своим собственным контрактом. Все это прекрасно работает. Конфигурация службы в приложении.конфигурация для сервиса выглядит так:

<services>
  <service behaviorConfiguration="WcfService.AlyzaServiceBehavior"
    name="Sam.Alyza.WcfService.ServiceWebsites">
    <endpoint address="" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceWebsites">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/Websites/" />
      </baseAddresses>
    </host>
  </service>
  <service behaviorConfiguration="Sam.Alyza.WcfService.LogReaderServiceBehavior"
    name="Sam.Alyza.WcfService.ServiceLogReader">
    <endpoint address="" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceLogReader">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/LogReader/" />
      </baseAddresses>
    </host>
  </service>
  <service behaviorConfiguration="Sam.Alyza.WcfService.ServiceSystemverwaltungBehavior"
    name="Sam.Alyza.WcfService.ServiceSystemverwaltung">
    <endpoint address="" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceSystemverwaltung">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/Systemverwaltung/" />
      </baseAddresses>
    </host>
  </service>
  [...]
</services>

поскольку у меня есть более крупный проект, с большим количеством контрактов, я хотел бы иметь способ разделить BaseAddress между различными контрактами на обслуживание.
Если бы это была только одна служба с разными контрактами и конечными точками, я мог бы установить базовый адрес ommon, но как установить общий baseaddress для более чем одной службы?

конечно, мне нужно что-то подобное для клиента.

3 ответов


вы можете объединить все контракты в одном классе, поэтому у вас есть одна служба с baseaddress и одна (или более) конечная точка(ы) для каждого контракта.

чтобы избежать одного большого файла класса, вы можете использовать ключевое слово partial (asuming вы используете c#), чтобы разделить класс на несколько файлов. Каждый файл может реализовать один контракт, что значительно упрощает обслуживание отдельных интерфейсов.

В C++ вы можете использовать #includes или множественное наследование, но это подразумевает большое количество дисциплина...

ваша конфигурация будет выглядеть так:

<services>
  <service behaviorConfiguration="WcfService.AlyzaServiceBehavior"
    name="Sam.Alyza.WcfService.ServiceAll">
    <endpoint address="Websites/" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceWebsites">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="LogReader/" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceLogReader">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="Systemverwaltung/" binding="netTcpBinding" contract="Sam.Alyza.WcfInterface.IServiceSystemverwaltung">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/" />
      </baseAddresses>
    </host>
  </service>
</services>

службы могут совместно использовать значения BaseAddress (включая порт #, если сеть.Служба совместного использования портов Tcp запущена). Это адреса конечных точек, которые должны быть уникальными. Обратите внимание в файле конфигурации, что конечные точки MEX для каждого ServiceHost имеют адрес "mex". Другие конечные точки имеют адрес пустой строки. Когда вы предоставляете относительный адрес для конечной точки WCF (по крайней мере, в файле конфигурации), базовый адрес добавляется к нему. Таким образом адрес конечной точки MEX для Служба LogReader-это " net.tcp://localhost: 8731/Design_Time_Addresses/SamAlyza / LogReader / mex".

поскольку относительный адрес не был установлен на конечной точке основной службы, базовый адрес ServiceHost используется в качестве фактического адреса для конечной точки основной службы. Поскольку никакие две конечные точки не могут иметь перекрывающийся Uri.Absolutepath значения, ваш пример приведет вас к мысли, что значения базового адреса не могут быть общими. Класс ServiceHost, в котором размещаются службы WCF, не имеет встроенная конечная точка, в то время как класс ServiceEndpoint имеет свойство ListenUri, которое будет заполняться на основе заданных параметров.

Если вы измените значения baseAddress в своем примере на все совпадения, пока вы устанавливаете уникальные относительные значения адресов на элементах конечной точки, все должно работать. Однако, похоже, что вы можете столкнуться с некоторыми проблемами с конечными точками MEX, так как все они имеют адрес "mex" в настоящее время. Сделайте их уникальными, и вы должны быть штраф.

теперь, я должен спросить, вы уверены, что вы не просто хотите, чтобы эти службы разделяли пространство имен, а не базовые адреса?


вы также можете установить базовые адреса в коде, если вы используете пользовательский ServiceHostFactory.

в config вы можете иметь некоторые настройки приложения:

<configuration>
  <appSettings>
    <add key="BaseAddress" value="http://localhost:1234" />
  </appSettings>
<configuration>

затем сделайте пользовательский ServiceHostFactory:

public sealed class MyServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        var baseAddy = ConfigurationManager.AppSettings["BaseAddress"];
        baseAddresses.Add(new Uri(baseAddy));
        return new ServiceHost(serviceType, baseAddresses);
    }

}

тогда вы также должны изменить свой .svc-файлы для использования этой фабрики:

<%@ ServiceHost Language="C#" Debug="true" Service="MyApp.MyService" CodeBehind="MyService.svc.cs" Factory="MyApp.MyServiceHostFactory" %>