几个WCF服务可以共享一个公共BaseAddress吗?
-
10-07-2019 - |
题
我有一个包含多个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。
如果这只是一个具有不同合同和端点的服务,我可以设置一个ommon baseaddress,但是如何为多个服务设置一个公共baseaddress?
当然,我需要为客户提供类似的东西。
解决方案
您可以将所有合同合并到一个类中,因此每个合同都有一个带有baseaddress和一个(或多个)端点的服务。
为避免使用一个大型类文件,您可以使用partial-keyword(假设您使用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值(包括端口#,如果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 <!>”;目前。做那些独特的,你应该没事。
现在,我必须问一下,你确定你不是只想让这些服务共享命名空间而不是基地址吗?
如果使用自定义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" %>