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

StackOverflow https://stackoverflow.com/questions/2500336

  •  21-09-2019
  •  | 
  •  

Вопрос

У меня есть только простые типы данных в сигнатуре метода службы (например, 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, приведение типов завершается неудачей.

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

Это было полезно?

Решение

Как вы заметили, вам необходимо предоставить производную службу (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);

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top