SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Silverlight 4で作る新しいRIAアプリケーション

WCF RIA Servicesの仕組み

Silverlight 4で作る新しいRIAアプリケーション(4)

  • X ポスト
  • このエントリーをはてなブックマークに追加

ダウンロード sample.zip (793.6 KB)

メタデータクラスによる表示データの制御と値の検証

 メタデータクラスはエンティティクラスの対となるクラスで、エンティティデータの属性情報を定義するクラスです。対になって1つのクラスを表すため、「バディクラス」と呼ばれることもあります。

 Visual Studioのウィザードからドメインサービスを作成すると、エンティティクラスのインナークラスとして、メタデータクラスが作成されます。

 WCF RIA Servicesでは、データの検証情報やUIに表示させるための表示名、表示順序などのメタ情報をメタデータクラス側に定義することで、エンティティクラス側がウィザードなどで再生成されても、ユーザが定義したメタ情報が失われないようになっています。

 リスト1は、お小遣い明細クラスに対し、メタデータクラスを通じてデータの表示方法や検証情報を追加した例です。データアノテーションを利用した値の検証については、過去記事『Silverlight 3で強化されたスタイルと値の検証』(CodeZine)を参照してください。

リスト1 お小遣い明細クラスのメタデータクラス(属性追加後)
[MetadataTypeAttribute(typeof(お小遣い明細.お小遣い明細Metadata))] 
public partial class お小遣い明細 
{ 
     internal sealed class お小遣い明細Metadata 
     { 
          private お小遣い明細Metadata() { } 
          [Display(Name = "日付", Order = 0)] 
          public DateTime 日付 { get; set; } 

          [Display(Order = 1)] 
          [Range(0, 20, ErrorMessage="{0}は{1}から{2}の間で入力してください。")] 
          public int 連番 { get; set; } 

          // ...  略 ... 

          [Include] 
          public byte[] TimeStamp { get; set; } 
          [Exclude] 
          public Nullable<DateTime> 最終更新日 { get; set; } 
    }
}   

 ここで注目するのは、お小遣い明細クラスに指定された属性情報です。MetadataTypeAttribute属性は、指定されたクラスに対するメタデータクラスを指定するための属性です。

 お小遣い明細クラスの本体は「お小遣いEntites.Designer.cs」にパーシャルクラスとして定義されているので、ここではメタデータクラスの指定のみを行っています。

 前編でデータグリッドに表示するサンプルを作成した後なので、Silverlight側のUIには特に変化はありません。しかし、Display属性を定義することで、UIを定義する際に、カラムの表示名やカラムの表示順といった情報をVisual Studioのデザイナーに伝えることができます。

 また、最終更新日プロパティはサーバ側で自動的に割り振るデータであるため、クライアント側には追加されないように、Exclude属性を追加しています。逆に、クライアント側に追加する場合に指定する属性は、Include属性です。Include属性はデフォルトで有効になるため、明示的に定義する必要はありません。

 この状態で前編のサンプルを起動し、連番に「21」といった範囲外の数字を入力すると、図4のように値の検証が行われ、正しい値を入力するか、入力をキャンセルするまでデータを確定できません。

図4 メタデータによる値の検証
図4 メタデータによる値の検証

 では、自動生成されたコード側を確認してみましょう。Silverlightプロジェクトの「Generated_Code」フォルダの「RIAServicesSample.Web.g.cs」から、お小遣い明細クラスを探してください。リスト1で定義した通り、自動生成されたコードでは、お小遣い明細Metadataクラスの情報が、お小遣い明細クラスのプロパティに定義されていることを確認できます(リスト2)。

リスト2 自動生成されたお小遣い明細クラス(属性追加後)
/// <summary> 
/// Gets or sets the '連番' value. 
/// </summary> 
[DataMember()] 
[Display(Name="連番", Order=1)] 
[Range(0, 20, ErrorMessage="{0}は{1}から{2}の間で入力してください。")] 
public int 連番 
{ 
    get 
    {  
         return this._連番; 
     } 
     set 
     { 
          if ((this._連番 != value)) 
          { 
              this.On連番Changing(value); 
              this.RaiseDataMemberChanging("連番"); 
              this.ValidateProperty("連番", value); 
              this._連番 = value; 
              this.RaiseDataMemberChanged("連番"); 
              this.On連番Changed(); 
          } 
    } 
} 

 このようにメタデータクラスを利用することで、データの検証情報とデザイン時の表示内容を、サーバ側で定義できます。

共有コード

 ここまでで、エンティティクラスにはデータモデルの定義を、メタデータクラスにはデータの属性情報を定義してきました。では、データの振る舞いを追加するには、どんな方法があるでしょうか。1つは後述するドメインサービスに定義する方法で、もう1つは共有コードに記述する方法です。

 共有コードは、サーバとクライアントでコードを共有するしくみです。例えば、新しくお小遣い帳のレコードを作成して初期化するコードは、サーバ側とクライアント側で同じコードを利用するはずです。このようなコードを記述したい場合、「*.share.cs」といった命名規則のクラスをソリューションに追加します。

 ここでは、お小遣い帳クラスのパーシャルクラスとして「お小遣い明細.share.cs」という名前の共有コードを作成しました。共有コードを配置する場所はWCF RIA Serviceリンクが設定されたプロジェクトであれば、どこであっても問題ありません。重要なのは、拡張子が「*.share.cs」であることです。

 ドメインサービスに定義されたメソッドの違いは、ドメインサービスのメソッドはあくまでサーバにあり、WCFを通じて呼び出すのに対し、共有コードのメソッドはクライアントにコピーされ、クライアントで動作します。

 今回追加した共有コードをリスト3に示します。この例では、単純にお小遣い明細の日付プロパティに当日の日付を設定しているだけです。

リスト3 お小遣い明細の新しいレコードを初期化する共有コード
partial class お小遣い明細 
{ 
     public static お小遣い明細 Create() 
     { 
          return new お小遣い明細 
          { 
              日付 = DateTime.Today 
          }; 
     } 
} 

 このコードをコンパイルすると、Silverlightプロジェクトの「Generate_Code」フォルダに、サーバ側のプロジェクトで定義した「お小遣い明細.shared.cs」と同じファイルが生成されるのを確認できます。このように共有コードを利用することで、エンティティのパーシャルクラスのコードやユーティリティクラスのコードを、サーバとクライアントで共有できます(図5)。

図5 共有コードの追加と自動生成
図5 共有コードの追加と自動生成
ドメインサービスと共有コード

 WCF RIA Servicesを利用していると、サーバ側に登録されたサービスであっても、まるでローカルにあるクラスのメソッドのように利用できます。当たり前のことですが、サーバ側に登録されたサービスを利用するには、データセンターなどの遠隔地にあるサービスを呼び出すことになり、パフォーマンス面では大きなデメリットになります。

 この手の問題は、開発時には、サービスを提供するサーバと、Silverlightが動作するサーバが同じであるため問題になりませんが、サービス提供時やパフォーマンステスト時など、プロジェクト後半になって問題が表面化することが多いです。

 一概にこうすれば良いという解決策はありませんが、特にサーバリソースを必要としないユーティリティ的なロジックは、共有コードにしてクライアント側にコードを同期させるというのも、1つの方法だと筆者は考えます。

次のページ
ドメインサービスを利用したデータの操作の概要

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Silverlight 4で作る新しいRIAアプリケーション連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト かるあ (杉山 洋一)(カルア(スギヤマ ヨウイチ))

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/5606 2010/12/28 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング