简体   繁体   English

有趣的WCF接口投射行为

[英]Interesting WCF interface casting behaviour

While answering another question I bumped into this interesting situation Where WCF is happy to cast an interface with different number of members and from Different namespaces where normal .net runtime can't. 在回答另一个问题时,我碰到了一种有趣的情况,WCF很乐意使用普通的.net运行时无法使用的具有不同数量成员的接口和来自不同命名空间的接口。

Can any one explain how WCF is able to do it and how to configure/force WCF to behave same as normal .net runtime. 谁能解释WCF如何做到这一点,以及如何配置/强制WCF与正常的.net运行时相同。 Please note that I know I should have only one interface and blah.. blah.. 请注意,我知道我应该只有一个接口等等。等等。

here is working code 这是工作代码

using System;
using System.Runtime.Serialization;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

namespace MyClient
{
  [ServiceContract]
  public interface IService
  {
    [OperationContract]
    string Method(string dd);
    [OperationContract]
    string Method2(string dd);
  }
}

namespace MyServer
{
  [ServiceContract]
  public interface IService
  {
    [OperationContract]
    string Method(string dd);
  }
}

namespace MySpace
{
  public class Service : MyServer.IService
  {
    public string Method(string dd)
    {
      dd = dd + " String from Server.";
      return dd;
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      string Url = "http://localhost:8000/";
      Binding binding = new BasicHttpBinding();
      ServiceHost host = new ServiceHost(typeof(Service));
      host.AddServiceEndpoint(typeof(MyServer.IService), binding, Url);
      host.AddDefaultEndpoints();
      host.Open();

      // Following line gives error as it should do. 
      //MyClient.IService iservice = (MyClient.IService)new MySpace.Service(); 

      // but WCF is happy to do it ;)
      ChannelFactory<MyClient.IService> fac = new ChannelFactory<MyClient.IService>(binding);
      fac.Open();
      MyClient.IService proxy = fac.CreateChannel(new EndpointAddress(Url));


      string d = proxy.Method("String from client.");
      fac.Close();
      host.Close();
      Console.WriteLine("Result after calling \n " + d);

      Console.ReadLine();


    }
  }
}

There is no inconsistency. 没有不一致的地方。

      // Following line gives error, as it should do, because the .NET types 
      // MyClient.IService and MySpace.Service are not related.   
      MyClient.IService iservice = (MyClient.IService)new MySpace.Service();   // ERROR !!

      // Likewise, a WCF client proxy defined using MyService.IService as the contract
      // cannot be cast to the unrelated .NET type MyClient.IService
      ChannelFactory<MyService.IService> fac1 = new ChannelFactory<MyService.IService>(binding); 
      fac1.Open(); 
      MyClient.IService proxy = (MyClient.IService)fac1.CreateChannel(new EndpointAddress(Url));  // ERROR !!

      // but the service can be consumed by any WCF client proxy for which the contract 
      // matches the defined service contract (i.e. they both expect the same XML infoset 
      // in the request and response messages). There is no dependency between the .NET type 
      // used in the client code and the .NET type used to implement the service. 
      ChannelFactory<MyClient.IService> fac = new ChannelFactory<MyClient.IService>(binding); 
      fac.Open(); 
      // Next line does not error because the ChannelFactory instance is explicitly 
      // specialised to return a MyClient.IService so the .NET type is the same... there is no cast
      MyClient.IService proxy = fac.CreateChannel(new EndpointAddress(Url)); 
      // NOTE: Thus far we have not done anything with the service in this case.
      // If we call Method() it should succeed, since the contract matches. If we call
      // Method2() the channel will fault as there is no matching operation contract in the service.

The .NET type system is a completely different concept to the WCF notion of service/operation/message/data contract. .NET类型系统与WCF服务/操作/消息/数据协定的概念完全不同。 Just as well, otherwise you could never write a WCF client for a WCF service you didn't write yourself. 同样,否则您将永远无法为自己编写的WCF服务编写WCF客户端。

However, as the middle example shows, if you reuse the .NET type for the service contract in both service and client code, your expectation will be met. 但是,如中间示例所示,如果在服务代码和客户端代码中都将.NET类型用于服务协定,则将满足您的期望。

Your MyClient.IService has the same method as MyServer.IService does WCF's channel factory thinks that the contract matches on the exposed url and hence processes the request. 您的MyClient.IService与MyServer.IService具有相同的方法,WCF的渠道工厂认为合同在公开的URL上匹配,因此处理了请求。

Try changing your MyClient.IService method name and you can see it fail. 尝试更改MyClient.IService方法名称,您会看到它失败。 Namespace are logical seperations as we know. 众所周知,命名空间是逻辑分隔。

When you create a WCF Service and expose the wsdl it doesn't have any of your namespaces, unless you specify one in your configuration using bindingNamespace attribute in your endpoint element. 创建WCF服务并公开wsdl时,它没有任何名称空间,除非您在配置中使用终结点元素中的bindingNamespace属性指定一个名称空间。 Just try a sample and generate a proxy from the wsdl to see that the proxy doesn't have any namespace. 只需尝试一个示例并从wsdl生成一个代理,以查看该代理没有任何名称空间。

As long as the IService in your MyClient and MyServer namespace match your WCF code above would work 只要您的MyClient和MyServer命名空间中的IService与上面的WCF代码匹配,

In regards to your code below: 关于下面的代码:

MyClient.IService iservice = (MyClient.IService)new MySpace.Service();       

You are trying to cast MySpace.Service explicitly to MyClient.IService where your "Service" doesnt implement your MyClient.IService and is correct according to OOP. 您试图将MySpace.Service显式转换为MyClient.IService,其中“服务”未实现MyClient.IService,并且根据OOP是正确的。 Since you have all the code in a single file and is self hosted might be giving you the confusion. 由于您将所有代码都放在一个文件中并且是自托管的,因此可能会使您感到困惑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM