2011-12-20 14 views
0

別の質問に答えると、WCFが異なる数のメンバーと、通常の.netランタイムではできない異なる名前空間からのインターフェイスをキャストできて、この面白い状況に遭遇しました。興味深いWCFインターフェイスのキャスティング動作

どのようにしてWCFがそれを行うことができるか、WCFが通常の.netランタイムと同じように動作するように設定/強制する方法について説明できます。私は1つのインターフェイスだけを持っている必要があります知っていることに注意してくださいと

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(); 


    } 
    } 
} 

答えて

3

矛盾はありません。

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

.NETタイプのシステムは、service/operation/message/dataコントラクトのWCFという概念とはまったく異なる概念です。ちょうどそうでなければ、自分で書いたことのないWCFサービス用のWCFクライアントを書くことはできません。

しかし、中間の例に示すように、サービスとクライアントコードの両方でサービスタイプの.NETタイプを再利用すると、期待通りの結果が得られます。

+0

Chrisは説明することができます "//サービスは、契約 //が定義されたサービス契約と一致するすべてのWCFクライアントプロキシによって消費される可能性があります(つまり、要求と応答メッセージで同じXMLインフォセット // )。 " –

+0

契約がどのようにマッチングしているのか、なぜその理由が異なるのですか? –

+1

私は "契約が定義された**運用**契約に一致する"と言ったはずです。サーバースタックは、クライアントスタックが要求メッセージをどのように構築したかについて何も知らないため、クライアントがクライアント側のチャネルランタイムを構築するための特別なメソッドを含むインターフェイスを使用していることは分かりません。すべてのサービスは、サービス契約のもとで有効な操作「メソッド」の要求インフォセットであるため、喜んで応答します。 –

2

あなたMyClient.IServiceがMyServer.IServiceと同様の方法でWCFのチャネルファクトリが考えるんたコードに取り組んでいる何とか...何とか..

ここ

公開されたURL上で契約が一致し、したがってリクエストを処理します。

MyClient.IServiceメソッド名を変更してみると、失敗することがわかります。ネームスペースは、われわれが知っているように論理的な分離です。

WCFサービスを作成してwsdlを公開すると、エンドポイント要素のbindingNamespace属性を使用して構成内に名前空間を指定しない限り、名前空間はありません。単にサンプルを試し、wsdlからプロキシを生成して、プロキシに名前空間がないことを確認してください。

限り、上記のあなたのWCFのコードは以下のコードに関しては

を働くだろうあなたのMyClientというおよびMyServerを名前空間一致でIServiceとして:あなたが明示的にMySpace.Serviceをキャストしようとしている

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

あなたの "サービス"があなたのMyClient.IServiceを実装していないMyClient.IServiceは、OOPに従って正しいです。 1つのファイルにすべてのコードがあり、自己ホストされているので、混乱を招く可能性があります。

+0

Rajesh、私はあなたの名前空間のポイントを理解しています。私はまだプロキシクラスが、あるメソッドを持つインターフェイスを2つのメソッドを持つインターフェイスにキャストする方法について頭を悩ますことはできませんか? –

+0

1つのメソッドを持つインターフェイスを2つのメソッドのインターフェイスにキャストしていますか? – Rajesh

+0

あまりにも多すぎるかもしれません私の頭にRemotingとOOPSがある場合は、バインディングEndPointを作成しているときにMyServer.IServiceを使用していて、クライアントからインターフェイスにMyClient.IServiceインターフェイスを要求しています任意のエンドポイントから公開 –