いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

WCF入門-001 (簡単なサンプル, 自己ホスト形式, コードで記述)


WCFの試験を受けるので、ただいま勉強中・・・。
とりあえず、片っ端からメモメモ。


WCFを利用する場合、System.ServiceModel名前空間
クラスを利用する。System.ServiceModelはデフォルトで
参照設定されていないので、まずこれを参照追加する。


以下、WCFHello Worldみたいなサンプルです。
app.configの利用は無し。全部コードで記述しています。


まず、サービスインターフェースの定義。

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;

namespace Gsf.Samples.WCF
{
    /// <summary>
    /// サービスインターフェースの定義です。
    /// </summary>
    /// <remarks>
    /// WCFでは、サービスを定義する際に
    ///    1.インターフェースを定義
    ///    2.実装クラスを定義
    /// を行う。
    /// 
    /// サービスインターフェースには、WCFにて用意されている
    /// 属性を付与する。
    /// 
    /// 尚、ServiceContractのNamespaceに指定している名称は
    /// 同ホスト内にて、名前が衝突しないようにするために付与されているものであり
    /// オプション扱いとなっている。
    /// 
    /// Namespaceに設定する値は、URL形式で設定するのが通例となっているが
    /// このURLは存在するURLを設定する必要はない。(かぶらなければ何でもよい。)
    /// 別に指定する値はURLで無くてもよい。
    /// </remarks>
    [ServiceContract(Namespace="http://Gsf.Samples.WCF/")]
    public interface IMyService
    {
        /// <summary>
        /// サービスメソッドの定義です。
        /// </summary>
        /// <param name="name">名前</param>
        /// <returns>指定された名前に対する挨拶文字列</returns>
        /// <remarks>
        /// WCFにて、サービスメソッドとして公開するメソッドは
        /// OperationContract属性を付与する。
        /// </remarks>
        [OperationContract]
        string SayHello(string name);
    }
}


次にサービスクラス。

using System;
using System.Collections.Generic;
using System.Linq;

namespace Gsf.Samples.WCF
{
    /// <summary>
    /// サービスの実装クラスです。
    /// </summary>
    /// <remarks>
    /// サービスの実装クラスに対して、ServiceContractは必要ありません。
    /// </remarks>
    public class MyService : IMyService
    {
        /// <summary>
        /// 指定した名前に対する挨拶文字列を返します。
        /// </summary>
        /// <param name="name">名前</param>
        /// <returns>挨拶文字列</returns>
        /// <remarks>
        /// サービスの実装に対しては、OperationContractは必要ありません。
        /// </remarks>
        public string SayHello(string name)
        {
            Console.WriteLine("[CALL] MyService.SayHello()");
            return string.Format("Hello. '{0}'!", name);
        }
    }
}


ホストするクラス。

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;

namespace Gsf.Samples.WCF
{
    /// <summary>
    /// アプリケーションエントリポイントを持つクラスです。
    /// </summary>
    /// <remarks>
    /// このサンプルでは、WCFの最も基本的な処理を記述しています。
    /// また、本サンプルでは必要な処理部分を全てコードで記述しています。
    /// </remarks>
    class Program
    {
        private const string SERVICE_BASE_ADDRESS = @"http://localhost:8081/WCFSample001";
        private const string ENDPOINT_ADDRESS     = "SayHello";

        /// <summary>
        /// アプリケーションエントリポイントです。
        /// </summary>
        static void Main()
        {
            //
            // サービスホストの構築.
            //
            // WCFにて、ホスト側は以下の処理を行う必要がある。
            //
            //   1.ServiceHostの構築
            //   2.Endpointの追加
            //   3.ホストのOpen
            //
            // 本サンプルは、自己ホスト形式となっている。
            // 自己ホストとは、一つの処理にてホストの構築とサービスの定義の
            // 両方を行っているものを指す。
            //
            // 通常、WCFでは自己ホスト形式でサービスを作成せず、サービス定義部分は
            // ライブラリとして定義し、ホスト部分は別の処理にて作成する。
            //
            // さらに、エンドポイントアドレスの設定などは、アプリケーション構成ファイルに
            // 設定するのが通例となる。
            //
            using (ServiceHost host = CreateServiceHost())
            {
                //
                // サービスエンドポイントを追加.
                //   サービスは、「ベースアドレス+サービスエンドポイント」で一意となる。
                // AddServiceEndpointメソッドには、ABCを指定する必要がある。
                //
                // アドレス (A) (ベースアドレスに対する相対パス)
                string           address  = ENDPOINT_ADDRESS;                
                // バインディング (B)
                BasicHttpBinding binding  = new BasicHttpBinding();
                // コントラクト (C)
                Type             contract = typeof(IMyService);

                host.AddServiceEndpoint(contract, binding, address);

                //
                // サービスをオープン.
                //
                host.Open();
                Console.WriteLine("サービスを開始しました。");
                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();

                //
                // サービスを終了.
                //
                host.Close();
            }
        }

        /// <summary>
        /// ServiceHostを構築します。
        /// </summary>
        /// <returns>ServiceHostオブジェクト</returns>
        private static ServiceHost CreateServiceHost()
        {
            //
            // アプリケーション構成ファイルを利用せず、ServiceHostを構築する場合は
            // 以下の情報を与える必要がある。
            //
            //    ・サービスの型(インターフェースではなく、実装クラス)
            //    ・ベースアドレス
            //
            Type serviceType = typeof(MyService);
            Uri  baseAddress = new Uri(SERVICE_BASE_ADDRESS);
            
            return new ServiceHost(serviceType, baseAddress);
        }
    }
}


クライアント側。今回はWinFormsで記述しています。

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Windows.Forms;

namespace Gsf.Samples.WCF
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// エンドポイントアドレス
        /// </summary>
        private const string ENDPOINT_ADDRESS = @"http://localhost:8081/WCFSample001/SayHello";

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            lblResult.Text = string.Empty;
            ActiveControl  = btnCallSerivceMethod;
        }

        private void btnCallSerivceMethod_Click(object sender, EventArgs e)
        {
            //
            // クライアントの構築.
            //
            // WCFにて、クライアント側は以下の処理を行う必要がある。
            //
            //   1.エンドポイントアドレスの構築
            //   2.ChannelFactoryの構築
            //   3.サービスの呼び出し
            //
            // 通常、WCFでは直接ChannelFactoryなどを構築せず
            // 「サービス参照の追加」を利用して、クライアントプロキシを自動生成する。
            //
            // さらに、エンドポイントアドレスの設定などは、アプリケーション構成ファイルに
            // 設定するのが通例となる。
            //
            // エンドポイントアドレスの構築.
            EndpointAddress endpointAddr = new EndpointAddress(ENDPOINT_ADDRESS);

            string result = String.Empty;
            try
            {
                //
                // チャネルを構築しサービス呼び出しを行う.
                //
                using (ChannelFactory<IMyService> channel = new ChannelFactory<IMyService>(new BasicHttpBinding()))
                {
                    //
                    // サービスへのプロキシを取得.
                    //
                    IMyService service = channel.CreateChannel(endpointAddr);

                    //
                    // サービスメソッドの呼び出し.
                    //
                    result = service.SayHello("WCF Study");

                    //
                    // チャネルを閉じる.
                    //
                    channel.Close();
                }
            }
            catch (CommunicationException ex)
            {
                //
                // エラーが発生.
                // 
                // WCFでは、サービスとクライアント間の通信中にエラーが発生した場合
                // CommunicationExceptionがスローされる。
                //
                MessageBox.Show(ex.Message);
            }

            lblResult.Text = result;
        }
    }
}


実行すると以下のようになります。


サンプルは以下の場所にアップしてあります。
https://sites.google.com/site/gsfzero1/Home/WCF-Sample-001.zip?attredirects=0&d=1


================================
過去の記事については、以下のページからご参照下さい。