クライアント コード生成
WCF RIA サービス を使用して Silverlight プロジェクトと中間層プロジェクトをリンクすると、RIA サービス により、中間層で公開したエンティティおよび操作に基づいて、クライアント アプリケーションのクライアント プロキシ クラスが生成されます。RIA サービス によってこれらのクラスが生成されるため、中間層からプレゼンテーション層にアプリケーション ロジックを複製する必要はありません。中間層コードに加えた変更は、クライアント プロジェクトをリビルドするときにプレゼンテーション層コードと同期されます。RIA サービス リンクをソリューションに追加すると、クライアント プロジェクトのコードを生成する前に強制的にサーバー プロジェクトをビルドする明示的なビルド依存関係がソリューションに追加されます。
生成されたコードは、クライアント プロジェクトの Generated_Code という名前のフォルダーにあります。このフォルダーを表示するには、クライアント プロジェクトのソリューション エクスプローラーで [すべてのファイルを表示] をクリックする必要があります。Generated_Code フォルダー内のクラスは直接変更しないでください。これらは、クライアント プロジェクトがリビルドされるときに上書きされます。ただし、生成されたファイルを開いて、クライアント プロジェクトで使用可能なコードを表示することは可能です。
クライアント コードを生成するアルゴリズムは、次の基本的な規則に従っています。
ドメイン サービス クラス、エンティティ クラス、または共有コードの中間層プロジェクトによってビルドまたは参照されるすべてのアセンブリを分析します。
EnableClientAccessAttribute 属性を使用して注釈が付けられている各ドメイン サービスでは、DomainContext クラスから派生するクラスを生成します。
ドメイン サービス クラスのクエリ メソッド、名前付き更新メソッド (UsingCustomMethod プロパティが true に設定されている更新メソッド)、または呼び出し操作それぞれでは、ドメイン コンテキスト クラスにメソッドを生成します。
ドメイン サービスによって公開される各エンティティ クラスでは、エンティティ プロキシ クラスを生成します。エンティティ クラスは、クエリ メソッドによって返されるときに公開されます。
共有対象としてマークされているコードをクライアント プロジェクトにコピーします。
次の図は、中間層プロジェクトに対して生成されたクライアント コードを示しています。
DomainService と DomainContext
DomainContext から派生するクラスは、次の規則に従って、各ドメイン サービス クラスに対して生成されます。
ドメイン サービスと同じ名前空間を使用したドメイン コンテキスト クラスが生成されます。
ドメイン コンテキスト クラスには、次の 3 つのコンストラクターが含まれています。
WebDomainClient クラスを使用して http 経由でドメイン サービスと通信するために必要な URI を埋め込む、既定のコンストラクター。
クライアントに代替 URI の指定を許可するコンストラクター。
クライアントにカスタム DomainClient 実装の指定を許可するコンストラクター (この実装は、通常、単体テストまたはカスタム トランスポート層へのリダイレクトに使用されます)。
ドメイン サービス クラス内の各クエリ メソッドでは、クライアント プロジェクトでエンティティを読み込むために使用できる EntityQuery メソッドを生成します。
各呼び出し操作では、操作を非同期に呼び出すために使用できる、対応する InvokeOperation メソッドを生成します。
Update(UsingCustomMethod=true) 属性でマークされた各メソッドでは、そのメソッドを呼び出したり、そのメソッドが呼び出されたかどうかを確認したりするメソッドを生成します。
挿入、更新、または削除を実行する、ドメイン サービス内のパブリック メソッドにより、ドメイン コンテキスト内に生成された EntityContainer は、クライアントで許可されている操作を示す EntitySetOperations フラグを使用して構築されます。
エンティティ クラスとエンティティ プロキシ クラス
エンティティ プロキシ クラスを生成する場合は、次の規則が適用されます。
中間層内のエンティティ クラスと同じ名前および名前空間でプロキシ クラスが生成されます。
ルート エンティティ型はエンティティ クラスから派生します。派生したエンティティ型は、中間層によって公開された対応する基本型から派生します。
サポートされる型を含んでおり、エンティティ クラス内の ExcludeAttribute 属性でマークされていないパブリック プロパティはすべて、そのプロパティがクライアント プロジェクト内に既に存在する場合を除いて、プロキシ クラス内に生成されます。詳細については、このトピックで後述される「メンバーの重複の回避」を参照してください。Object はサポートされている型ではありません。
各プロパティの setter に含まれるコードでは、検証が実行され、プロパティが変更されていることおよび変更されたことをクライアントに通知します。
メタデータ属性は、生成されたコード内のエンティティ クラスと組み合わされます。クライアントにはメタデータ クラスは存在しません。
可能な場合は、カスタム属性がプロキシ クラスに反映されます。クライアント プロジェクトに存在するカスタム属性に必要な条件の詳細については、次の「カスタム属性」を参照してください。
メンバーの CustomValidationAttribute の複数のインスタンスで同じ型と検証メソッドが指定されている場合は、1 つの CustomValidationAttribute のみがそのメンバーに反映されます。
カスタム属性
カスタム属性を追加してもクライアント プロジェクトでコンパイル エラーが発生しない場合、カスタム属性はプロキシ クラスに反映されます。カスタム属性を反映させるには、次の条件が必要です。
カスタム属性の型はクライアント プロジェクトで使用できる必要があります。
カスタム属性宣言で指定されたすべての型はクライアント プロジェクトで使用できる必要があります。
カスタム属性の型は、そのすべてのプロパティのパブリック setter を公開するか、パブリック setter のないプロパティの設定を可能にするコンストラクターを公開する必要があります。
必要なカスタム属性がクライアントに反映されない場合は、クライアント プロジェクトにアセンブリ参照を追加する必要があります。カスタム属性に必要なアセンブリへの参照を追加して、クライアント プロジェクトでコンパイルします。また、カスタム属性は、共有ファイル内で定義することにより、層の間で共有することもできます。
共有コード
中間層とプレゼンテーション層の間でコード ファイルを共有すると、クライアント プロジェクトを変更しなくてもコードがコピーされます。共有対象のファイルを指定するには、*.shared.cs
パターンまたは *.shared.vb
パターンを使用してそのファイルに名前を付けます。共有ファイルを含む中間層プロジェクトのディレクトリ構造は、Generated_Code フォルダーの下にレプリケートされます。
カスタム型を共有コード ファイルに追加した後、呼び出し操作からその型を返しても、ドメイン コンテキスト内に生成されたメソッドはカスタム型を返しません。代わりに、ドメイン コンテキスト内のメソッドによって、フレームワークに含まれている型が返されます。たとえば、IDictionary を実装する MyCustomDictionary
という名前のカスタム型を作成し、その型をドメイン操作の戻り値として指定すると、ドメイン コンテキスト内に生成されたメソッドは MyCustomDictionary
を返しません。代わりに、Dictionary オブジェクトを返します。
詳細については、「共有コード」を参照してください。
メンバーの重複の回避
エンティティ プロキシ クラスを生成すると、部分型が使用されることにより、クライアント プロジェクトでは同じ型とメンバーが既に定義されている可能性があります。共有コードまたはクライアント プロジェクトにのみ存在するコードで既にメンバーを定義している場合があります。RIA サービス では、プロキシ クラスを生成する前に既存のメンバーがチェックされます。既に定義されているメンバーは、プロキシ クラスには生成されません。