如何在单个端点上的WCF服务中公开具有多重继承的服务契约接口

时间:2010-03-23 13:44:59

标签: interface wcf servicecontract

我在服务的方法签名中只有简单的数据类型(例如int,string)。我的服务类实现了单个ServiceContract接口,比如IMathService,而这个接口又继承了其他一些基本接口,比如IAdderService。我想在单个端点上使用接口契约IAdderService作为服务公开MathService。但是,一些了解IMathService的clinet应该能够访问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 instnace强制转换为IMathService,它失败了,我在客户端获得了IMathService的null实例。

我的观察是,如果服务器向客户端公开IMathService,那么客户端可以安全地类型转换为IAdderService,反之亦然。但是,如果服务器公开IAdderService,那么类型转换将失败。

这有什么解决方案吗?或者我是以错误的方式做到的。

2 个答案:

答案 0 :(得分:0)

正如您所观察到的,您必须公开派生服务(MathService)而不是AdderService。

WCF不知道AdderService实际上是实现MathService接口的MathService。它被视为AdderService - 因此无法将其强制转换为派生类。

答案 1 :(得分:0)

除了使用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);

这对我有用。您不能将基类型转换为派生类型。但是你可以反过来。