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 サポート 中村 憲一郎