複数の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を共有する方法が欲しいです。
これが異なるコントラクトとエンドポイントを持つ1つのサービスである場合、ommonベースアドレスを設定できますが、複数のサービスに共通のベースアドレスを設定するにはどうすればよいですか?
もちろん、クライアントにも同様のものが必要です。
解決
すべてのコントラクトを1つのクラスに組み合わせることができるため、1つのサービスに1つのベースアドレスと、1つのコントラクトごとに1つ(または複数)のエンドポイントがあります。
1つの大きなクラスファイルを持たないようにするには、部分キーワード(c#を使用すると仮定)を使用して、クラスを複数のファイルに分割できます。各ファイルは1つのコントラクトを実装できるため、個々のインターフェイスのメンテナンスがはるかに簡単になります。
C ++では、#includeまたは多重継承を使用できますが、これは大量の規律を意味します...
設定は次のようになります:
<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エンドポイントのアドレスが&quot; mex&quot;であることに注意してください。他のエンドポイントのアドレスは空の文字列です。エンドポイントの相対アドレスを(少なくとも構成ファイルで)WCFに提供すると、ベースアドレスがそれに付加されます。したがって、LogReaderサービスのMEXエンドポイントアドレスは&quot; net.tcp:// localhost:8731 / Design_Time_Addresses / SamAlyza / LogReader / mex&quot;です。
メインサービスエンドポイントに相対アドレスが設定されていないため、ServiceHostのベースアドレスがメインサービスエンドポイントの実際のアドレスとして使用されます。 2つのエンドポイントが重複するUri.AbsolutePath値を持つことはできないため、この例では、ベースアドレス値を共有できないと考えるようになります。 WCFサービスをホストするServiceHostクラスには組み込みのエンドポイントがありませんが、ServiceEndpointクラスには、指定した設定に基づいて設定されるListenUriプロパティがあります。
例のbaseAddress値をすべて一致するように変更した場合、エンドポイント要素に一意の相対アドレス値を設定する限り、すべてが機能するはずです。ただし、MEXエンドポイントにはすべてアドレス「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" %>