Dynamics CRM 2011 CrmSvcUtil ツールとその拡張方法 (フィルタリング)

みなさん、こんにちは。

今回から 2 回にわたり、開発で欠かせない CrmSvcUtil ツールとその拡張方法を紹介します。
まずはどのような時に CrmSvcUtil.exe を利用するかを説明します。

事前バインド

SDK を利用した開発時に、エンティティに関連する操作を行うとします。提供されている SDK アセンブリは
エンティティの情報を保持しておらず、またカスタムエンティティやフィールド情報を事前に知る由もない
ため、以下のように記述する必要があります。

// 取引先企業オブジェクトの作成
Entity account = new Entity("account");
// 名前フィールドに値を設定
account["name"] = "サンプル取引先企業";
// Create メソッドでのレコード作成
accountId = _service.Create(account);

上記のように、エンティティ名やフィールド名は全て文字列として指定する必要があり、IntelliSense が
利用できません。また文字列に間違いがあってもコンパイル時にエラーが出ることはなく、実行時に
初めてエラーが確認できます。

一方事前バインドを利用した場合、以下のような記述が可能です。

Account account = new Account();
account.Name = "サンプル取引先企業";
accountId = _service.Create(account);

取引先企業オブジェクトは Account という型が利用でき、またフィールドも型指定可能です。よって
問題があればコンパイル時に分かりますし、IntelliSense も機能します。

CrmSvcUtil.exe ツール

事前バインドを利用するためには、現在システムで利用できる情報を取得する必要があります。
CrmSvcUtil.exe を利用すれば、事前バインド用のカスタムコードを生成でき、生成されたファイルには、
システムエンティティ以外にも、全てのカスタムエンティティの情報が含まれます。

さらに名前空間の指定や、LINQ をサポートする OrganizationServiceContext も生成可能です。

CrmSvcUtil.exe の利用方法

CrmSvcUtil.exe はコマンドラインツールです。Dynamics CRM サーバーの URL や認証情報を
引数として渡すことで、自動的にファイルを生成します。設置側、IFD、オンライン問わず利用できる
優れたツールです。詳細は以下の URL を参照してください。

コード生成ツール (CrmSvcUtil.exe) を使用して事前バインド型エンティティ クラスを作成する
https://msdn.microsoft.com/ja-jp/library/gg327844.aspx

CrmSvcUtil の拡張 ‐ フィルタリング

CrmSvcUtil を利用することで事前バインド用の情報を取得可能ですが、そのまま実行すると全ての
エンティティ等の情報を取得するため、例えば取引先企業エンティティの情報のみ必要な場合には
無駄な情報を多く含んだコードが生成されることになります。

そこで CrmSvcUtil.exe を拡張し、コード生成時の動作を変更する必要が出てきます。動作を変更
するには、カスタムアセンブリを作成して、CrmSvcUtil.exe 実行時のパラメーターとして指定します。

実際にカスタムアセンブリのサンプルが提供されていますので、確認してみましょう。

1. 以下のサンプルを Visual Studio 2010 で開きます。
sdk\samplecode\cs\crmsvcutilextensions\basicfilteringservice

2. プロジェクトの参照設定より sdk\bin\crmsvcutil.exe および sdk\bin\microsoft.xrm.sdk.dll を
追加します。

3. BasicFilteringService.cs を開いて、中身を確認、編集します。

BasicFilteringService クラスは ICodeWriterFilterService インターフェースを継承しています。
またインターフェースで定義されているメソッドを実装しています。各メソッドでは、生成される
コードに追加されるオブジェクトを決定するためのもので、bool を返します。

例えばエンティティの情報を生成されたコードに追加するかどうかは、以下のメソッドの戻り値で
判定しています。

bool ICodeWriterFilterService.GenerateEntity(EntityMetadata entityMetadata, IServiceProvider services)
{
    if (!entityMetadata.IsCustomEntity.GetValueOrDefault()) { return false; }
    return this.DefaultService.GenerateEntity(entityMetadata, services);
}

このサンプルでは、エンティティがカスタムエンティティかどうかを確認して、カスタムの場合
false、それ以外では true を返しています。今回は取引先企業の情報のみ返したいので
以下のように変更します。

bool ICodeWriterFilterService.GenerateEntity(EntityMetadata entityMetadata, IServiceProvider services)
{
    // エンティティの名称が account の場合のみ true を返す
    if (entityMetadata.LogicalName == "account") { return true; }
    return false;
}

4. ビルドメニューよりプロジェクトをビルドします。

5. ビルドが完了したら、プロジェクトの Debug フォルダに移動します。
sdk\samplecode\cs\crmsvcutilextensions\basicfilteringservice\bin\Debug

6. コマンドプロンプトを起動して、上記フォルダに移動後、CrmSvcUtil コマンドを、以下の
パラメーターを付け足して実行します。前半はクラス名、後半はアセンブリ名です。

/codewriterfilter :"BasicFilteringService,CrmSvcUtilExtensions"

私の環境では、以下のコマンドを実行しました。

CrmSvcUtil.exe /codewriterfilter :"BasicFilteringService,CrmSvcUtilExtensions"
/url:https://crm1srv:5555/CRM/XRMServices/2011/Organization.svc
/out:FilteredXrm.cs

7. 生成された FilteredXrm.cs を開いて、取引先企業の情報だけを含んでいるか確認します。
取引先企業の情報のみであるため、ファイルサイズも非常に小さくなります。

その他の拡張

CrmSvcUtil.exe の拡張はフィルタリング以外にも、以下の制御が可能です。以下は
SDK からの抜粋です。

インターフェイス名 : ICodeCustomizationService
CodeDOM の生成が完了した後で呼び出されます (ICodeGenerationService の既定のインスタンスを使用すると仮定します)。候補リスト内の定数など、追加のクラスを生成するには便利です。

インターフェイス名 : ICodeWriterFilterService
特定のオブジェクト/プロパティを生成するかどうかを確認するために CodeDOM の生成中に呼び出されます (ICodeGenerationService の既定のインスタンスを使用すると仮定します)。

インターフェイス名 : ICodeWriterMessageFilterService
特定のメッセージを生成するかどうかを確認するために CodeDOM の生成中に呼び出されます (ICodeGenerationService の既定のインスタンスを使用すると仮定します)。このパラメーターは、要求/応答として使用しないでください。要求/応答は、Microsoft.Crm.Sdk.Proxy.dll および Microsoft.Xrm.Sdk.dll で生成済みとなっているからです。

インターフェイス名 : IMetadataProviderService
サーバーからメタデータを取得するために呼び出されます。生成プロセス中に複数回呼び出されることがあるため、データはキャッシュに保存する必要があります。

インターフェイス名 : ICodeGenerationService
CodeDOM 生成の中心的な実装部分。これを変更した場合、他の拡張機能が説明どおりに動作しなくなる可能性があります。

インターフェイス名 : INamingService
オブジェクトの名前を確認するために CodeDOM 生成中に呼び出されます (既定の実装を使用すると仮定します)。

まとめ

CrmSvcUtil.exe は拡張なしで実行しても十分利用価値が高いツールですが、独自に
拡張することで無駄な情報を出さないようにしたり、逆に足りない情報を付加することが
可能となります。

次回は足りない情報を付加する方法を紹介します。お楽しみに。

- Dynamics CRM サポート 中村 憲一郎