12

我有一个包含几个 WCF 服务的程序集,每个服务都有自己的合同。这一切都很好。该服务的 app.config 中的服务配置如下所示:

<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。
如果这只是一个具有不同合约和端点的服务,我可以设置一个通用的基地址,但是如何为多个服务设置一个通用的基地址?

当然,我需要为客户提供类似的东西。

4

3 回答 3

10

您可以将所有合约合并到一个类中,这样您就拥有一个带有基地址的服务和每个合约一个(或多个)端点。

为了避免拥有一个大的类文件,您可以使用部分关键字(假设您使用 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>
于 2009-01-13T09:15:55.580 回答
2

服务可以共享 BaseAddress 值(包括端口号,如果 Net.Tcp 端口共享服务正在运行)。端点地址必须是唯一的。请注意,在您的配置文件中,每个 ServiceHost 的 MEX 端点的地址为“mex”。您的其他端点的地址为空字符串。当您向 WCF 提供端点的相对地址时(至少在配置文件中),基地址会附加到它的前面。因此,LogReader 服务的 MEX 端点地址是“net.tcp://localhost:8731/Design_Time_Addresses/SamAlyza/LogReader/mex”。

由于未在主服务端点上设置相对地址,因此将 ServiceHost 的基地址用作主服务端点的实际地址。因为没有两个端点可以有重叠的 Uri.AbsolutePath 值,所以您的示例会让您相信基地址值不能共享。托管 WCF 服务的 ServiceHost 类没有内置终结点,而 ServiceEndpoint 类有一个 ListenUri 属性,该属性将根据您提供的设置进行填充。

如果您将示例中的 baseAddress 值更改为全部匹配,只要您在 Endpoint 元素上设置唯一的相对地址值,一切都会正常工作。但是,您似乎可能会在使用 MEX 端点时遇到一些挑战,因为它们目前都有地址“mex”。让那些独一无二,你应该没问题。

现在,我必须问,您确定您不只是希望这些服务共享一个命名空间,而不是基地址吗?

于 2009-01-12T19:07:45.043 回答
2

如果使用自定义 ServiceHostFactory,还可以在代码中设置基地址。

在配置中,您可以进行一些应用设置:

<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" %>
于 2009-12-07T16:28:40.313 回答