開発手順は、先にサービス提供側を開発してから、クライアント側を開発するながれだと思う。
先にサービス側開発しないと、クライアントの開発ほぼ不可能の状態となる。
もしかしたら、サービス側で提供する機能のメソッドを宣言して置いて(実際の機能を実装しない)、一回発行してクライアント側の実装は、宣言したものによって、開発しやすくなると思う。
IISによって、サービスの提供は Visual Studio の 「Web」-「WCF サービス アプリケーション」テンプレートのプロジェクトを作成して、
これはサービス提供側のWEB端末となります。
作成したWEB端末にWCFサービスライブラリを追加するのは、Visual Studio の WCF から「WCFサービスライブラリ」テンプレートを利用して、
プロジェクトを作成する。
作成したWCFサービスライブラリプロジェクト、ディフォルトでは、IService1.cs と Service1.cs 二つファイルが追加されている。
これは、WCFサービス提供側のひなとなります。
何のプロジェクトでも構いません。Windows From 、Console、WPFなど
サービスを提供できるように、いくつやらないといけないことがあります。
例:
internal static ServiceHost myServiceHost = null;
サービス開始
Uri baseAddress = new Uri("http://localhost:8080/MemberService"); myServiceHost = new ServiceHost(typeof(SampleService),baseAddress); myServiceHost.Open(); serviceButton.Text = "Stop Service";
サービス停止
if (myServiceHost.State != CommunicationState.Closed) { myServiceHost.Close(); serviceButton.Text = "Start Service"; }
クライアントでは、何のプロジェクトでも構いません。Windows Form、Console、WPFなど
前提条件:サービス提供側を構築した状態。
svcutil.exe /language:cs /out:generatedProxy.cs /config:app.config http://192.168.11.2:8080/Service.svcまだ svcutil コマンドの使い方として、下記のような方法があります。
svcutil WCFSample.LongTimeService.dllメタファイルからプロキシを作成する
svcutil /namespace:*,WCFSample.Client handcraft.wcfsample.org.2008.05.17.wsdl *.xsd /out:Proxy.cs
「サービス参照の追加」によって、ソリューションに追加されたものからみて、判断した。
「IXXXService」
サービス側提供しているメソッドのインターフェイス。
インターフェイスの属性は[ServiceContract()]となります。
「XXXService」
「IXXXService」インターフェイスを実装したサービスクラス。
※具体的に、もっと活用的にこのクラスの中に何を実装すればいいかはっきり分からないが、一応インターフェイスの実装しなければならない。
「Member」クラス
これはデータのコンテナクラスとなります。
クラスの属性は[DataContract]となり、クラス中の各プロパティの属性は[DataMember]となります。
参照URL:
http://hyperthink.net/blog/servicehostfactory-vs-servicehostfactorybase/
もし直接 ServiceHostBase を継承して、カスタマイズしたホストを利用したい場合、ServiceHostFactoryBase を継承してやる。
you derive from ServiceHostFactoryBase directly if you're trying to use a custom host that derives directly from ServiceHostBase.
ServiceHostFactoryBase は ServiceHost の指示における Service 属性を通して、渡された不透明な文字列からServiceHostBasesを作成します。
ServiceHostFactoryBase creates ServiceHostBases from an opaque string passed in through the Service attribute in the @ServiceHost directive.
CLR型名以外の何かとしてService指示のそのコンテンツを解釈したいなら、ServiceHostFactoryBaseを継承して、あなたは、やりたい方法でその文字列を分析できます。
If you want to interpret that contents of the Service directive as something other than a CLR type name, you can derive from ServiceHostFactoryBase and parse that string in whatever way you want.
もし ServiceHost を継承する代わりに、サービスホストをカスタマイズしたい場合、ServiceHostFactory を継承してやる。
If your custom service host instead derives from ServiceHost, you write a factory that derives from ServiceHostFactory.~
もし異なる ServiceHost の派生型を利用したい場合、ServiceHostFactory を継承して、自分のカスタマイズファクトリを作成する。
If you want to use a different subtype of ServiceHost, write your own factory that derives from ServiceHostFactory.
ServiceHostFactory をディフォルトファクトリとして用意され、CLR 型名として、コンストラクタを解釈する。ServiceHost の新しいインスタンスを作成する際に利用する。
We ship a default factory called ServiceHostFactory that interprets the constructor string as a CLR type name and uses that to create new instances of ServiceHost.
WCFサービスクラスはデフォルトではクライアントとのセッションが維持されます。つまり、クライアントの接続があると、対応する1つのサービスクラスのインスタンスが作成されます。つまり1000クライアントから同時接続されると、1000ものインスタンスが作成されます。これはサービスクラスに付与する ServiceBehavor.InstanceContextMode のデフォルト値がInstanceContextMode.PerSessionとなっているためです。InstanceContextModeの種類は次のとおり
PerSession | ServiceBehavior のデフォルト値.各セッション(クライアントから接続があるたび)に、新しくインスタンスが作成されます。 OperationBehavior.ReleaseInstanceModeを指定しない限り、クライアントのプロキシを閉じると、インスタンスが破棄されます。 |
PerCall | クライアントがサービスメソッドを呼び出すたびに、新しくインスタンスが作成されます。このモードではセッションごとにインスタンスが作成されないので、スケーラビリティが改善されます。ただし、状態を維持する必要がある場合は、独自で状態管理の方法を実装する必要があります。 |
Single | サービスクラスの1つのインスタンスのみ作成されます。複数のクライアントが接続しても、サービスクラスのインスタンスは1つのみとなります。このインスタンスはWCFのホストプログラムが停止したときのみ破棄されます。 |
以下のようにサービスクラスのServiceBehaviorAttributeで指定します。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] public class ProductService : IProductService {....}
ServiceBehavior.InstanceContextModeをInstanceContextMode.Single とすると、同時に複数のクライアントがサービスメソッドを呼び出しても同時に1つの要求のみが処理されます。そのため、多くのクライアントからリクエストを受けるとタイムアウトが大量に発生する可能性があります。これを避ける場合のひとつの方法として、 ServiceBehavior.ConcurrencyModeをSingle(デフォルト)からMultiple にすることで、複数のリクエストを同時に処理できるようになります。ただし、スレッドセーフではなくなるので、同期が必要な処理はサービスクラスの定義者が実装する必要があります。ServiceConcurrencyMode.Reentrantはサービスクラス自身はシングルスレッドで実行されますが、サービスクラス内で別のサービスを呼び出し、呼び出し先の別サービスからコールバックメソッドを呼び出すことができるようにするモードです。
OperationBehavior.ReleaseInstanceModeにReleaseInstanceMode.None以外の値を設定することで、インスタンスの生存期間をコントロールできます。ServiceBehavior.ContextModeがPerSessionのときに組み合わせて使用すると効果があります。
AfterCall | サービスメソッド呼び出し後にインスタンスを破棄する。 |
BeforeCall | サービスメソッド呼び出し前に既存のインスタンスを破棄し、新しいインスタンスを作成する。 |
BeforeAndAfterCall | サービスメソッド呼び出し前に新しいインスタンスを作成し、呼び出し後にインスタンスを破棄する。 |
None | デフォルトの値。インスタンスの破棄はServiceBehavior.InstanceContextModeにより決定される。 |
ServiceContract.SessionMode, OperationContract.IsInitiating, OperationContract.IsTerminatingを使用して、サービスメソッドの呼び出し順(開始、途中、最後)を強制できるようになります。上述のプロパティはWCFに特化した処理であり、WCF以外のクライアントとの互換性に影響が発生します。詳細内容はMSDNを参照して下さい。
WCFのサービス側で throw new FaultException() すると、その例外はクライアント側に通知されるようになっている。クライアント側でも catch(FaultException e) で受け取り。
更に FaultException<T> というジェネリックも定義されていて、 FaultException に俺クラスの情報を付与して例外発生できる。というか受け側で catch(FaultException<T> e) によって選別できるのがうれしい。ただし、これを実現するためのプロキシクラス作成には svcutil コマンドを利用する必要がある。 WSDL 経由では例外に関するメタデータが公開されないようだ。
サービス アプリケーションで System.ServiceModel.Dispatcher.IDispatchMessageInspector を実装すれば、送受信する際に転送されてるデータをチェックできる。
System.ServiceModel.Configuration.BehaviorExtensionElement の実装は、構成ファイルからメッセージ インスペクタ動作を使用できるようにするためです。~
実装例:
// BehaviorExtensionElement members public override Type BehaviorType { get { return typeof(EndpointBehaviorMessageInspector); } } protected override object CreateBehavior() { return new EndpointBehaviorMessageInspector(); }
構成ファイル中の設定:
<extensions> <behaviorExtensions> <add name="endpointMessageInspector" type="Microsoft.WCF.Documentation.EndpointBehaviorMessageInspector,HostApplication" /> </behaviorExtensions> </extensions>