サービスコントラクトとChannelFactoryを使用してサービスプロキシクラスをクライアント実行中に作成してWCFサービスに接続してみます。今回のサンプルではサービスコントラクトのみをクライアントのプロジェクトに含めるようにしていますが、WCFサービスとクライアント間で既定で定義されていない複雑な型(DataContractやMessageContractでアノテートされたクラス)が必要な場合は、そのクラスもクライアントプロジェクトにdllの参照やソースファイルを追加することにより含める必要があります。

確認環境

  • Windows Vista Enterprise(クライアント,サービス同一マシン)
  • 開発環境:Visual Studio 2008 Professional (英語版)
  • 動作環境: .NET 3.5 自己ホスト
  • バインディング:net.tcp

1 ソリューションの作成

Visual Studioを起動して、メニューの[File]→[New]→[Project]をクリックし、Project typesでVisual Studio Solutions,TemplatesでBlank Solutionを選択し、WCFSample022という名前で空のプロジェクトを作成しました。

2.WCFサービスプロジェクトの作成

ソリューションエクスプローラ上でソリューションを右クリック→[Add]→[New Project]をクリック。Add New Projectダイアログで、テンプレートWCF Service Libraryを選択、プロジェクト名をWCFSample.Serviceで新規作成しました。既定で作成される、Service1.cs,IService1.cs,Web.configを削除します。

プロジェクトを右クリック→[Add]→[New Item]を選択します。Add New ItemダイアログのTemplatesからWCF Serviceを選択し、名前をHelloとして作成します。今回はサービスオペレーションを呼び出した返り値に整形されたメッセージを返すサービスを作成します。

作成されたIHello.csを編集します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WCFSample.Service
{
    [ServiceContract]
    public interface IHello
    {
        [OperationContract]
        string HelloMessage(string name);
    }
}

同様に、Hello.csを編集します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WCFSample.Service
{
    public class Hello : IHello
    {

        #region IHello Members

        public string HelloMessage(string name)
        {
            return "Hello " + name + ".";
        }

        #endregion
    }
}

Web.configが作成されている場合は削除します。

3.WCFサービスホストプロジェクトの作成

ソリューションエクスプローラ上でソリューションを右クリック→[Add]→[New Project]をクリック。Add New Projectダイアログで、WPF Applicationを選択し、WCFSample.Hostというプロジェクトを新規作成します。参照の追加で、WCFSample.Serviceプロジェクトを参照に追加します。加えて、System.ServiceModel.dllを参照に追加します。

プロジェクトw右クリック→[Add]→[New Item]で、Application Configuration Fileを選択、名前をApp.configで新規作成します。

3.1 構成ファイルの作成

App.configを右クリック[Edit WCF Configuration]を選択します。右ペインのCreate a New Serviceをクリックします。

ウィザードが表示されるので、次のように編集します。

(1) Service typeでWCFSample.Service.Helloを入力、Nextボタンをクリックします。確認メッセージが表示されてもOKをクリックします。

(2) Service contractでWCFSample.Service.IHelloを入力、Nextボタンをクリックします。

(3) communication modelでTCPを選択、Nextボタンをクリックします。

(4) Addressでnet.tcp://localhost:8080/HelloServiceを入力し、Nextボタンをクリックします。

(5) 設定の確認ダイアログが出力されるのでFinishボタンクリックします。

保存してWCF Configuration Editorを閉じます。

App.configの内容は次のようになります。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <services>
            <service name="WCFSample.Service.Hello">
                <endpoint address="net.tcp://localhost:8080/HelloService" binding="netTcpBinding"
                    bindingConfiguration="" contract="WCFSample.Service.IHello" />
            </service>
        </services>
    </system.serviceModel>
</configuration>

3.2 Window1.xaml,Window1.xaml.csを編集

サービスの開始、終了ボタンを持つWCFホストプログラムを作成します。

Window1.xamlを次のように編集します。

<Window x:Class="WCFSample.Host.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" SizeToContent="WidthAndHeight">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Button x:Name="btnStart" Grid.Row="0" Grid.Column="0" Content="Start" Margin="15" Width="50" Click="btnStart_Click"  />
        <Button x:Name="btnStop" Grid.Row="0" Grid.Column="1" Content="Stop" Margin="15" Width="50" Click="btnStop_Click" IsEnabled="False"/>
        <Label x:Name="lblState" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Content="サービスは開始されていません." />

    </Grid>
</Window>

同様にWindow1.xaml.csを編集します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ServiceModel;

namespace WCFSample.Host
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        ServiceHost _host = null;
        public Window1()
        {
            InitializeComponent();
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            _host = new ServiceHost(typeof(WCFSample.Service.Hello));
            _host.Open();
            lblState.Content = "サービス中...";
            btnStart.IsEnabled = false;
            btnStop.IsEnabled = true;
        }

        private void btnStop_Click(object sender, RoutedEventArgs e)
        {
            _host.Close();
            lblState.Content = "サービス停止";
            btnStop.IsEnabled = false;
            btnStart.IsEnabled = true;
        }
    }
}

プロジェクトをスタートアッププロジェクトにして動作確認をして完了です。

注意:Windows Filewallの確認画面が表示される場合はUnblockを選択してください。

 

4.WCFクライアントプロジェクトの作成

ソリューションを右クリック[Add]→[New Project]を選択します。Add New Projectダイアログで、Console Applicationを選択します。WCFSample.Clientというプロジェクト名で新規作成します。参照の追加でSystem.ServiceModelを追加します。

4.1 サービスコントラクトのコピー

WCFSample.ServiceプロジェクトのIHello.csをクライアントのプロジェクトにコピーします。今回は必要ありませんが、サービス,クライアント間で既定でシリアル化が定義されていないデータコントラクトやメッセージコントラクトアトリビュートが付与されたクラスもコピーする必要があります。

今回はWCFサービスプロジェクトからファイルをコピーしていますが、本来はサービスとメッセージ(DataContractなどが付与されたクラス)からなるプロジェクトを作成し、そのプロジェクトのdllをクライアントプロジェクトの参照に追加するようにします。サービス実装プロジェクトも同様にサービスコントラクトのみを定義したdllを参照し、サービスを実装するようにすべきだと考えます。

4.2 Program.csの編集

参照の追加でSystem.ServiceModelを追加したあと、メインプログラムを編集します。ChannelFactoryの型引数にサービスコントラクト型を指定してプログラム上でプロキシクラスを作成するようにしています。サービスのアドレスやバインディング構成はプログラム上で構成します。サービスとの接続を閉じる場合はプログラムのように、プロキシ変数をIClientChannelにキャストしてClose()を呼び出すことで行います。

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

namespace WCFSample.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Enter if service started");
            Console.ReadLine();
            try
            {
                NetTcpBinding binding = new NetTcpBinding(SecurityMode.Message);
                //NetTcpSecurity security = binding.Security;
                //security.Message.ClientCredentialType = MessageCredentialType.Windows;
                EndpointAddress address = new EndpointAddress("net.tcp://localhost:8080/HelloService");
                WCFSample.Service.IHello proxy = ChannelFactory<WCFSample.Service.IHello>.CreateChannel(binding, address);
                Console.WriteLine(proxy.HelloMessage("Tarou"));
                ((IClientChannel)proxy).Close();
                proxy = null;
            }
            catch (Exception e)
            {
                System.Console.WriteLine(e.Message);
            }
            Console.ReadLine();
        }
    }
}

ソリューションエクスプローラ上でソリューションを右クリックしプロパティを選択、プロパティ画面を表示します。Multiple Startupプロジェクトを選択し、WCFSample.Client,WCFSampleHostプロジェクトのアクションをStartに設定し、実行時にホスト、クライアントプロジェクトが実行されるようにします。WCFホストを開始し、動作することを確認します。

 

 

説明は以上です。間違い、指摘等がありましたら、ご連絡ください。

よろしくお願いします。