Udostępnij za pośrednictwem


Dynamics CRM : コードレビュー事例 : イメージを利用したプラグイン

みなさん、こんにちは。

今回は開発者の方向けの情報として、北米 PFE ブログからプラグインの
コーディングに関する記事を紹介します。

元情報 : Code Review: Refactored Handling of Plug-in Pre-Image Attribute Values

===============================================================
最近関わった Microsoft Dynamics CRM 2011 のプラグインに関するコードレビュー
プロジェクトで、カスタムコードが繰り返し利用されるパターンに気が付きました。
このような場合、繰り返されるコードをメソッドとして記述することで、プラグイン
で利用するコードをより簡潔にできると共に、メンテナンス性も向上します。

問題のコードは pre-image を利用して処理前のエンティティの列情報を確認する
ものですが、これは Update プラグインでよく利用されるシナリオです。Update
処理では、実際に更新される列の情報のみがプラグインに引き渡されるため、
その他の更新されない列の情報は確認が行えません。

イメージを利用することで、処理の前後におけるレコードの任意の列情報を
プラグインに引き渡すことが可能になります。この機能を利用すれば、不要な
Retreive をプラグイン内で実行する必要がなくなり、パフォーマンスが向上
しますが、フィールドの情報を取得する際、InputParameter と Image の両方
から値を取得する必要があります。通常以下の流れになります。

1. プライマリエンティティよりフィールドの値の取得を試みる。
2. 値が取得できた場合はそれを利用する。
3. 値が取得できない場合は、イメージから値の取得を試みる。
4. 値が取得できたらそれを利用する。
5. 値が取得できない場合は既定値を利用する。

実際のコードでは以下のようになります。

Common Scenario

int value = -1; //default value

if (entity.Contains("attributename"))
{
  value = entity.GetAttributeValue<int>("attributename");
}
elseif (preImage.Contains("attributename"))
{
  value = preImage.GetAttributeValue<int>("attributename");
}

次に上記処理をメソッド化してみます。ここでは拡張メソッドを利用します。

Extension Method

public static class EntityExtensions
{
  ///<summary>
  /// Extension method to get an attribute value from the entity
  /// or its image snapshot
  ///</summary>
  ///<typeparam name="T">The attribute type</typeparam>
  ///<param name="entity">The primary entity</param>
  ///<param name="attributeLogicalName">Logical name of the attribute</param>
  ///<param name="image">Image (pre/post) of the primary entity</param>
  ///<returns>The attribute value of type T</returns>
  ///<remarks>If neither entity contains the attribute, returns default(T)</remarks>
  public static T GetAttributeValue<T>(thisEntity entity,
                                       string attributeLogicalName,
                                       Entity image)
  {
   return entity.GetAttributeValue<T>(attributeLogicalName, image, default(T));
  }

  ///<summary>
  ///Extension method to get an attribute value from the entity or image
  ///</summary>
  ///<typeparam name="T">The attribute type</typeparam>
  ///<param name="entity">The primary entity</param>
  ///<param name="attributeLogicalName">Logical name of the attribute</param>
  ///<param name="image">Image (pre/post) of the primary entity</param>
  ///<param name="defaultValue">The default value to use</param>
  ///<returns>The attribute value of type T</returns>
  public static T GetAttributeValue<T>(thisEntity entity,
                                       string attributeLogicalName,
                                       Entity image,
                                       T defaultValue)
  {
      return entity.Contains(attributeLogicalName)
          ? entity.GetAttributeValue<T>(attributeLogicalName)
          : image != null && image.Contains(attributeLogicalName)
              ? image.GetAttributeValue<T>(attributeLogicalName)
              : defaultValue;
  }
}

このコードを利用すると、もともとのコードは以下のように変更できます。

Refactored Scenario

int value = entity.GetAttributeValue<int>("attributename", preImage, -1);

もし同じコードを何度も繰り返し記述するのであれば、メソッド化するべきです。

PFE で実施しているコードレビューサービスに興味がありますか?Microsoft
Dynamics CRM サービスを拡張するマネージドコードの解析から、クライアント
サイドで実装される JavaScript までレビュー対象であり、ベストプラクティスや
設計、セキュリティ、パフォーマンス、メンテナンス性、サポート性を考慮した
レビューを実施しています。また場合によってはサンプルコードを提示して
具体的に問題を指摘します。
===============================================================

まとめ

上記は北米 PFE のコードレビュー事例ですが、日本でも同様のサービスを
提供しています。興味があるお客様は是非契約担当までご相談ください。
尚、拡張メソッドについては以下の記事をご参照ください。

https://msdn.microsoft.com/ja-jp/library/vstudio/bb383977.aspx

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