かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

WCF RIA ServicesでHello world

Silverlight4 Toolsの正式版(英語版じゃないと使えないけど)が出てWCF RIA Servicesも正式なものになりました。ということで、ここらへんで軽くHello worldをしてみたいと思います。
作ろうと思うアプリケーションは、WCF RIA ServicesのデモではおなじみのEntity Frameworkとの連携するタイプのものではなくて、単一の自作のクラスをサーバーサイドから取得するようなイメージのものにしてみたいと思います。とりあえず、ゴールは、ボタンを押すとサーバーサイドからPersonクラスという人間を表すクラスのデータを取得して、画面上に「こんにちは、田中 太郎さん!!」と表示するようなものにします。田中 太郎の部分がサーバからWCF RIA Servicesを使って取得したものになる予定です。

プロジェクトの作成

まず、HelloRIAServicesと言う名前でSilverlight Applicationを新規作成してEnable WCF RIA Servicesにチェックを入れます。

このチェックは、Silverlight Applicationのプロパティから後で設定することもできますが、今回は最初から使うことがわかってるので有効にしておきます。

サーバーサイドの作成

次に、サーバーサイドを作りこんでいきます。サーバーサイドはDomainServiceというものを使ってクライアントにサービスを公開します。WCFを素で使うよりも構成ファイルをいちいち書かなくてよかったりして素敵な感じに使えるようになっています。早速新規作成からDomain Service Classを作成します。
名前は、PersonDomainServiceにしました。

よくあるサンプルだと、EntityFrameworkと連携するっていうことで、上の画面でエンテティを選択したりしますが、ここでは何もせずにOKを押します。そうすると、EnableClientAccess属性がついたDomainServiceクラスを継承するPersonDomainServiceクラスが作成されます。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;

namespace HelloRIAServices.Web
{
    [EnableClientAccess()]
    public class PersonDomainService : DomainService
    {
    }
}

この下に、今回サーバーとクライアント間のデータの受け渡しを行うためのPersonクラスを定義します。PersonクラスにはIDとNameプロパティを用意して、IDプロパティにはKey属性をつけます。このKey属性をつけないとWCF RIA Servicesでクライアントに公開することが出来ないので要注意です。
因みに、私はKey属性をつけるのをよく忘れます。

public class Person
{
    [Key]
    public int ID { get; set; }
    public string Name { get; set; }
}

そして、PersonDomainServiceクラスにPersonクラスを返すだけのGetPersonByNameメソッドを作成します。単純に、引数で渡された名前のPersonクラスを返すだけの単純な実装です。Hello worldだから、これくらい理解しやすくないとね。

[EnableClientAccess()]
public class PersonDomainService : DomainService
{
    public Person GetPersonByName(string name)
    {
        return new Person
        {
            ID = 0,
            Name = name
        };
    }
}

これで、ビルドすると裏でこっそりとSilverlight Application側にもコードが生成されていたりします。因みに単一のクラスを返すか、IQueryableを返すようなメソッドを作ると、自動的にクライアントからデータを取得することが出来るようになっています。
このときのメソッドの引数には、残念ながら独自のクラスとかは渡すようには出来なかったと思います。基本的な型くらいしか渡せないのはちょっと残念です。引数が増えたらどうしようという心配がありますね。

以上でサーバーサイドは完了です。一度ビルドしたら、次はSilverlight Applicationのほうの作成にうつります。

Silverlight Application側の作成

Silverlight Application側ではMainPage.xamlを開いてデザイナを使って以下のような画面をさくっと作ります。

TextBoxに名前を入れてボタンを押すとTextBlockにこんにちは***さんと表示されるという寸法です。早速挨拶ボタンのクリックイベントハンドラを作成していきます。挨拶ボタンをデザイナ上でダブルクリックするとクリックイベントのハンドラが作成されるので、そこに処理を書いていきます。

このボタンクリックイベントで作成するのはPersonDomainContextという名前のクラスになります。これは、WCF RIA Servicesが自動生成してくれたクラスで、サーバーサイドで作成したDomainServiceクラスのServiceという部分がContextという名前に置き換わるというルールで名前がつけられるみたいです。
今回の場合はPersonDomainServiceという名前でサーバーサイドのクラスを作ったのでPersonDomainContextになります。

DomainContextクラスでは、DomainServiceで作成したデータ取得系のメソッドにQueryとついたメソッドが作成されています。今回の場合は、GetPersonByNameという名前のメソッドをDomainServiceで作成したため、DomainContextにはGetPersonByNameQueryというメソッドが作成されています。
このメソッドはEntityQuery型を返して、サーバーへの問い合わせを表すっぽいです。このQueryオブジェクトをDomainContextのLoadメソッドに渡すことで、サーバーへの通信が行われる仕組みになっています。
Loadメソッドには第一引数にクエリ、第二引数にコールバック、第三引数に任意のオブジェクトを渡せるようになっています。今回は、第一引数にGetPersonByNameQueryの戻り値で、第二引数に完了時の処理、第三引数にはnullを渡します。

ということでコードは以下のような感じになります。

private void button1_Click(object sender, RoutedEventArgs e)
{
    var ctx = new PersonDomainContext();
    // クエリを作成して
    var q = ctx.GetPersonByNameQuery(textBox1.Text);
    // Loadメソッドで処理を呼び出す。第二引数は処理完了時に呼ばれるコールバック
    ctx.Load(q, op =>
    {
        // エラーがあったらエラーを表示する
        if (op.HasError)
        {
            textBlock1.Text = "エラーです";
            return;
        }

        // 結果から最初のデータを取り出して文字列に整形して出力
        var person = op.Entities.First();
        textBlock1.Text = string.Format("こんにちは{0}さん", person.Name);
    },
    null);
}

以上で完成です。

実行してみよう

実行すると、まず以下のような画面が起動してきます。

テキストボックスに田中 太郎と入力してボタンを押すと、こんにちは田中 太郎さんと表示されます。

とても簡単に作れました。気をつけないといけないのは、WCF RIA Servicesでやり取りするクラスには、どれかのプロパティにKey属性がついていないといけないということくらいです。通常はDBからとってきたデータを返すことになるので、Keyに該当する項目があるはずなので、そいつにつけることになると思います。

因みに、このHello worldアプリケーションのプロジェクトは、以下からダウンロードできます。
http://cid-c0989b857f2f850c.skydrive.live.com/self.aspx/%e5%85%ac%e9%96%8b/samples/HelloRIAServices.zip