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

发布于 2024-08-26 05:32:12 字数 3609 浏览 4 评论 0原文

我的服务方法签名中只有简单的数据类型(例如 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 实例类型转换为 IMathService,它失败,并且我在客户端获得 IMathService 的 null 实例。

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

有什么办法解决这个问题吗?或者我是以错误的方式做的。

I have only simple data types in method signature of service (such as int, string). My service class implements single ServiceContract interface say IMathService, and this interface in turn inherits from some other base interface say IAdderService. I want to expose the MathService using interface contract IAdderService as a service on a single endpoint. However some of the clinet's which know about IMathService should be able to access the extra services provided by IMathService on that single endpoint i.e. by just typecasting IAdderService to 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();

Server side Configuration:

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

Client Side imeplementation:

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

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

Client side configuration:

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

Using above code and configuration I am not able to typecast IAdderService instnace to IMathService, it fails and I get null instance of IMathService at client side.

My observation is if server exposes IMathService to client then client can safely typecast to IAdderService and vice versa is also possible. However if server exposes IAdderService then the typecast fails.

Is there any solution to this? or am I doing it in a wrong way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冧九 2024-09-02 05:32:12

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

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

Just as you observed, you have to expose the derived service (MathService) instead of the AdderService.

WCF has no idea that AdderService happens to actually be a MathService implementing a MathService interface. It is regarded as AdderService - so there is no way to cast it to a derived class.

凉墨 2024-09-02 05:32:12

我完全复制了您的情况,只是我使用了 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);

这对我有用。您无法将基类型强制转换为派生类型。但是,您也可以执行相反的操作。

I replicated your situation exactly except I used an IMathService endpoint rather than an IAdderService endpoint.

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

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

This works for me. You can't cast a base type to a derived type. You can do the reverse however.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文