Pregunta

Tengo un ensamblado que contiene varios servicios WCF, cada uno con su propio contrato. Todo funciona muy bien. La configuración del servicio en app.config para el servicio se ve así:

<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>

Dado que tengo un proyecto más grande en mente, con más contratos, me gustaría tener una manera de compartir BaseAddress entre los diferentes contratos de servicio.
Si esto fuera solo un servicio con diferentes contratos y puntos finales, podría establecer una dirección base ommon, pero ¿cómo configuro una dirección base común para más de un servicio?

Por supuesto que necesitaría algo similar para el cliente.

¿Fue útil?

Solución

Puede combinar todos los contratos en una clase, por lo que tiene un servicio con una dirección base y uno (o más) punto final (es) por contrato.

Para evitar tener un archivo de clase grande, puede usar la palabra clave parcial (suponiendo que use c #) para dividir la clase en varios archivos. Cada archivo puede implementar un contrato, lo que facilita el mantenimiento de las interfaces individuales.

En C ++ puede usar #incluye o herencia múltiple, pero eso implica una gran cantidad de disciplina ...

Su configuración se vería así:

<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>

Otros consejos

Los servicios pueden compartir valores de BaseAddress (incluidos los números de puerto, si se está ejecutando el servicio Net.Tcp Port Sharing). Las direcciones de punto final deben ser únicas. Observe en su archivo de configuración que los puntos finales MEX para cada ServiceHost tienen una dirección de "mex". Sus otros puntos finales tienen una dirección de cadena vacía. Cuando proporciona una dirección relativa para un punto final a WCF (al menos en el archivo de configuración), la dirección base se antepone a ella. Por lo tanto, la dirección de punto final MEX para el servicio LogReader es "net.tcp: // localhost: 8731 / Design_Time_Addresses / SamAlyza / LogReader / mex".

Dado que no se estableció una dirección relativa en el punto final del servicio principal, la dirección base del ServiceHost se usa como la dirección real para el punto final del servicio principal. Debido a que no hay dos puntos finales que puedan tener valores Uri.AbsolutePath superpuestos, su ejemplo lo llevaría a creer que los valores de la dirección base no se pueden compartir. La clase ServiceHost que aloja los servicios WCF no tiene un punto final incorporado, mientras que la clase ServiceEndpoint tiene una propiedad ListenUri que se completará en función de la configuración que proporcione.

Si cambia los valores de baseAddress en su ejemplo para que coincidan todos, siempre que establezca valores de dirección relativos únicos en los elementos Endpoint, todo debería funcionar. Sin embargo, parece que puede encontrarse con algunos desafíos con los puntos finales MEX, ya que todos tienen la dirección '' mex '' actualmente. Hazlos únicos y deberías estar bien.

Ahora, debo preguntar, ¿está seguro de que no quiere simplemente que estos servicios compartan un espacio de nombres, en lugar de direcciones base?

También puede establecer las direcciones base en el código si utiliza un ServiceHostFactory personalizado.

En la configuración puede tener alguna configuración de aplicación:

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

Luego haga un ServiceHostFactory personalizado:

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);
    }

}

Entonces también debe cambiar sus archivos .svc para usar esa fábrica:

<%@ ServiceHost Language="C#" Debug="true" Service="MyApp.MyService" CodeBehind="MyService.svc.cs" Factory="MyApp.MyServiceHostFactory" %>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top