Как предоставить интерфейсы контрактов на обслуживание с множественным наследованием в сервисе WCF на одной конечной точке

У меня есть только простые типы данных в сигнатуре метода службы (например, int, string). Мой класс обслуживания реализует один интерфейс ServiceContract, скажем, IMathService, и этот интерфейс, в свою очередь, наследуется от какого-то другого базового интерфейса, например, IAdderService. Я хочу представить MathService, используя контрактный интерфейс IAdderService в качестве службы на одной конечной точке. Однако некоторые из клиник, которые знают об IMathService, должны иметь возможность доступа к дополнительным службам, предоставляемым IMathService на этой единственной конечной точке, то есть просто путем типизации IAdderService для IMathService.

//Interfaces and classes at server side
[ServiceContract]
public interface IAdderService
{
[OperationContract]
int Add(int num1, int num2);
}

[ServiceContract]
public interface IMathService : IAdderService
{
[OperationContract]
int Substract(int num1, int num2);
}

public class MathService : IMathService
{
#region IMathService Members
public int Substract(int num1, int num2)
{
    return num1 - num2;
}
#endregion

#region IAdderService Members
public int Add(int num1, int num2)
{
    return num1 + num2;
}
#endregion
}

//Run WCF service as a singleton instace
MathService mathService = new MathService();
ServiceHost host = new ServiceHost(mathService);
host.Open();

Конфигурация на стороне сервера:

 <configuration>
   <system.serviceModel>
     <services>
            <service name="IAdderService"
         behaviorConfiguration="AdderServiceServiceBehavior"> 
        <endpoint address="net.pipe://localhost/AdderService"
      binding="netNamedPipeBinding"
      bindingConfiguration="Binding1"
      contract="TestApp.IAdderService" />
         <endpoint address="mex"
      binding="mexNamedPipeBinding"
      contract="IMetadataExchange" />
        <host>
           <baseAddresses>
            <add baseAddress="net.pipe://localhost/AdderService"/>
           </baseAddresses>
        </host>
           </service>
          </services>
       <bindings>
        <netNamedPipeBinding>
      <binding name="Binding1" >
          <security mode = "None">
           </security>
           </binding >
        </netNamedPipeBinding>
       </bindings>

      <behaviors>
        <serviceBehaviors>
     <behavior name="AdderServiceServiceBehavior">
            <serviceMetadata />
       <serviceDebug includeExceptionDetailInFaults="True" />
     </behavior>
        </serviceBehaviors>
      </behaviors>
     </system.serviceModel>
    </configuration>

Реализация клиентской части:

IAdderService adderService = new
ChannelFactory<IAdderService>("AdderService").CreateChannel();
int result = adderService.Add(10, 11);

IMathService mathService = adderService as IMathService; 
result = mathService.Substract(100, 9);

Конфигурация на стороне клиента:

    <configuration>
       <system.serviceModel>
          <client>
            <endpoint name="AdderService" address="net.pipe://localhost/AdderService" binding="netNamedPipeBinding" bindingConfiguration="Binding1" contract="TestApp.IAdderService" />
          </client>

          <bindings>
            <netNamedPipeBinding>
         <binding name="Binding1" maxBufferSize="65536" maxConnections="10">
          <security mode = "None">
          </security>
         </binding >
            </netNamedPipeBinding>
          </bindings>
        </system.serviceModel>
      </configuration>

Используя приведенный выше код и конфигурацию, я не могу типизировать экземпляр IAdderService в IMathService, он не работает, и я получаю нулевой экземпляр IMathService на стороне клиента.

Мое наблюдение состоит в том, что если сервер предоставляет IMathService клиенту, тогда клиент может безопасно ввести тип IAdderService и наоборот. Однако, если сервер предоставляет IAdderService, произойдет сбой приведения типа.

Есть ли какое-то решение этого? или я делаю это неправильно.

2 ответа

Решение

Как вы заметили, вы должны предоставить производную службу (MathService) вместо AdderService.

WCF не подозревает, что AdderService фактически является MathService, реализующим интерфейс MathService. Он рассматривается как AdderService - поэтому нет возможности привести его к производному классу.

Я точно повторил вашу ситуацию, за исключением того, что использовал IMathService конечная точка, а не IAdderService конечная точка.

IAdderService adderService = new ChannelFactory<IMathService>("MathService").CreateChannel();
int result = adderService.Add(10, 11);

IMathService mathService = adderService as IMathService;
result = mathService.Substract(100, 9);

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

Другие вопросы по тегам