プラグインを記述する

次の 2 つの方法のいずれかを使用して、プラグイン を作成できます。

  • Power Platform 開発ツールは、プラグインを作成する最新の方法を提供します。ここで言及されているツールは、Visual Studio 用の Power Platform ToolsPower Platform CLI です。 これらの Power Platform Tools はどちらも同様のプラグイン コードを生成するため、あるツールから別のツールへの移行は非常に簡単で理解しやすいものです。

    • Visual Studio の Power Platform Tools を使用して、テンプレート プラグイン コードを簡単に作成し、プラグインを登録 (デプロイ) します。 その方法については、クイックスタート 記事を参照してください。 Visual Studio で作業したい場合は、このツールを使用してください。

    • Power Platform CLI を使用して、単一の pac プラグイン コマンドを使った、テンプレート プラグイン コードが付いた基本 (Visual Studio 対応) プラグイン プロジェクトを作成します。 その後、 pac tool prt コマンドを使用して、プラグイン登録ツールをインタラクティブに使用して、作成したものを Microsoft Dataverse に登録します。 端末ウィンドウまたは Visual Studio Code で作業する場合は、この CLI ツール セットを使用してください。

  • Visual Studio またはお気に入りのエディタを使用してコードを手動で作成します。 この記事では、Dataverse API を使用したコードの作成に焦点を当てていますが、紹介された概念は、前述のツールを使用したプラグイン開発にも当てはまります。

IPlugin インターフェイス

プラグインは、.NET Framework 4.6.2 を対象としてビルドされたアセンブリ内のコンパイル済みクラスです。 イベント パイプライン ステップに登録されるプラグイン プロジェクトの各クラスは、単一の IPlugin.Execute メソッドを定義する、IPlugin インターフェイスを実装する必要があります。

public class MyPlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        throw new NotImplementedException();
    }
}

Execute メソッドは、単一の IServiceProviderパラメーターを受け取ります。 IServiceProvider には、単一のメソッド: GetService があります。 コードで使用可能な複数の異なる種類のサービスを取得するには、このメソッドを使用します。

詳細: コードで使用可能なサービス

重要

IPlugin から派生する場合、クラスはステートレスで書き込む必要があります。 これは、プラットフォームがクラス インスタンスをキャッシュし、パフォーマンス上の理由から再利用するためです。 これについて考える簡単な方法は、クラスにプロパティまたはメソッドを追加するべきではなく、すべてのものは Execute メソッド内に含める必要があるということです。

プラグインの作成に Power Platform Tools 拡張子または Power Platform CLI を使用する場合、生成された PluginBase クラスは IPlugin インターフェイスを実装しています。

上記の注記のプロパティまたはメソッドの追加に関する記述には、いくつかの例外があります。 たとえば、定数を表すプロパティを持つことができる場合には、Execute メソッドから呼び出されるメソッドを持つことができます。 重要なことは、クラスのプロパティとして、サービス インスタンスやコンテキスト データを格納しないことです。 これらの値はそれぞれの呼び出しで変わり、そのデータがキャッシュされたり、それ以降の呼び出しに適用されないようにします。

詳細: IPlugin の実装をステートレスとして開発する

プラグインへの構成データの引き渡し

プラグインを登録するときに、実行時にプラグインに渡す構成データをオプションで指定できます。 構成データによって、登録されたプラグインの特定のインスタンスがどのように実行されるかを定義できます。 この情報は、クラスのコンストラクターのパラメーターに文字列データとして渡されます。 unsecuresecure という、2 つのパラメーターがあります。 最初の unsecure パラメーターは、他の人に見えても構わないデータに使用します。 機密データには 2 番目の secure パラメーターを使用します。

次のコードは、MyPlugin という名前のプラグイン クラスに対する可能な 3 つのコンストラクター署名を示しています。

public MyPlugin() {}
public MyPlugin(string unsecure) {}  
public MyPlugin(string unsecure, string secure) {}

セキュリティで保護された構成データは、システム管理者のみが読み取り特権がある別のテーブルに格納されます。

詳細: プラグイン登録手順 > 構成データの設定

PluginBase 抽象クラス

PluginBase クラスは IPlugin インターフェイスを実装しています。 このクラスが提供される理由は、商用ソリューションで実証された堅牢なプログラミング パターンを実装するためです。 ただし、プラグイン コードでのこのクラスの使用はオプションですが、推奨されます。

このクラスを使用できる SDK アセンブリは存在せず、いずれかのツールでクラスを生成する必要があります。 クラスを生成する際は、Visual Studio の Power Platform Tools 拡張機能でプラグイン プロジェクトを作成するか、または Power Platform CLI コマンド pac plugin init を実行します。 生成されたプロジェクトには PluginBase.cs ファイルが含まれています。

詳細情報: pac プラグインクイック スタート: Power Platform Tools でプラグインを作成する

重要

Power Platform Tools 拡張機能と Power Platform CLI で生成された PluginBase クラスは、クラス メンバーの署名が若干異なります。 どちらかを選択し、それをすべてのプラグイン コード開発で使用するのが最善の方法です。 どちらのバージョンのクラスも同じ機能を持ち、同様に実行されます。

PluginBase に関連する主要なインターフェイスとクラスを、このクラスの図に視覚的に示します。

PluginBase クラスとその他の関連タイプ。

Plugin1 サンプル クラス (図を参照) は PluginBase から派生したものです。 この Plugin1 クラスの名前を独自のカスタム名に変更し、コードを追加して ExecuteDataversePlugin メソッドとクラス コンストラクターを実装します。 LocalPluginContext クラスは、プラグインで使用できる指定されたサービス参照とエンドポイントで、自動的に初期化されます。 IPlugin インターフェイスを実装した場合は、これらすべてのサービスとエンドポイントを使用する前に、それらを初期化するコードを必ず記述してください。

コードで使用可能なサービス

通常、プラグイン内で必要な事柄には次ようなものが考えられます:

  • プラグインに渡されたコンテキスト データにアクセスして、イベントを発生させ、プラグインを呼び出したエンティティとメッセージ リクエストに関する情報を特定します。 このデータは実行コンテキストと呼ばれます。
  • .NET 用 SDK 呼び出しを使用して Organization Web サービスにアクセスし、クエリ、作成、更新、削除などのメッセージ要求操作を実行します。
  • プラグイン コードをどのように実行しているかを評価できるように、メッセージをトレース サービス に記述します。

注意

プラグインが通常使用するすべての Dataverse サービスとプラグイン実行コンテキストは事前に構成されており、PluginBase クラスからプラグインを派生する際にプラグイン コードで使用できます。

IServiceProvider.GetService メソッドは、必要に応じて実行コンテキストで渡されたサービス参照にアクセスする方法を提供します。 サービスのインスタンスを取得するには、サービスの種類を渡す GetService メソッドを呼び出します。 この方法については、次のセクションで詳しく説明します。

実行コンテキスト

実行コンテキストには、プラグインが必要とする可能性のある豊富な情報が含まれています。 コンテキストは、次のコードを使用して取得されます。

IPluginExecutionContext context = (IPluginExecutionContext)
    serviceProvider.GetService(typeof(IPluginExecutionContext));

詳細: IPluginExecutionContext実行コンテキストを理解する

組織 Web サービス

実行コンテキストで渡されるデータに加えて、Dataverse テーブルの行データは、Organization Webサービスへの SDK 呼び出しを使用してプラグイン コードから読み書きできます。 Web API はプラグインでサポートされていないため、使用しないでください。また、ユーザーはプラグインの実行前に事前認証されるため、Web サービスにアクセスする前にユーザーを認証しないでください。

詳細: テーブル操作メッセージの使用

Organization Web サービスへのオブジェクト参照を取得するには、次のコードを使用します。

IOrganizationServiceFactory serviceFactory =
    (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService orgService = serviceFactory.CreateOrganizationService(context.UserId);

サービスのトレース

プラグインを実行した場合に発生することを把握するためにログを確認できるよう、トレース サービスを使用して PluginTraceLog テーブル にメッセージを記述します。

トレース ログに書き込む場合は、トレース サービスのインスタンスを取得する必要があります。 次のコードは、IServiceProvider.GetService を使用してトレース サービスのインスタンスを取得する方法を示しています メソッド。

ITracingService tracingService =
    (ITracingService)serviceProvider.GetService(typeof(ITracingService));

トレースに記述するには、ITracingService.Trace を使用します。 メソッド。

tracingService.Trace("Write {0} {1}.", "your", "message");

詳細: トレースを使うロギングとトレース

その他のサービス

Azure Service Bus 統合を使用してプラグインを記述する場合、IServiceEndpointNotificationService インターフェイスを実装する通知サービスを使用しますが、このインターフェイスについてはここで解説しません。

詳細: Azure 統合

まとめ

前に説明したプラグインの概念を適用すると、プラグイン コードは次のようになります。

public class MyPlugin : PluginBase
{
  // Constructor
  public MyPlugin(string unsecureConfiguration, string secureConfiguration)
       : base(typeof(MyPlugin))
  { }

  protected override void ExecuteDataversePlugin(ILocalPluginContext localPluginContext)
  {
    if (localPluginContext == null)
    {
      throw new ArgumentNullException(nameof(localPluginContext));
    }

    var context        = localPluginContext.PluginExecutionContext;
    var serviceFactory = localPluginContext.OrgSvcFactory;
    var tracingService = localPluginContext.TracingService;

    try
    {
      // TODO Plug-in business logic goes here. You can access data in the context,
      // and make calls to the Organization web service using the Dataverse SDK.
    }
    catch (FaultException<OrganizationServiceFault> ex)
    {
      throw new InvalidPluginExecutionException("The following error occurred in MyPlugin.", ex);
    }
    catch (Exception ex)
    {
        tracingService.Trace("MyPlugin: error: {0}", ex.ToString());
        throw;
    }
  }
}

これら 2 つのプラグイン実装方法は、FollowupPlugin コード サンプルで確認できます。 プラグインでの例外への対応に関する詳細については、プラグインで例外に対処する を参照してください。 

プラグインの設計がパフォーマンスに影響します

プラグインを作成するときは、プラグインが効率的かつ迅速に実行されることが重要です。 プラグインの実行時間が長ければ長いほど、メッセージ操作を呼び出した (プラグインをトリガーした) エンドユーザーを待たせることになります。 メッセージ操作の処理に加えて、Dataverse プラグインを含むパイプラインに登録されているすべての同期プラグインを実行します。 プラグインの実行に時間がかかりすぎる場合、またはパイプラインに登録されているプラグインが多すぎる場合、これによるパフォーマンスへの影響により、アプリケーション UI が応答しなくなったり、最悪の場合、パイプライン ロールバックによるタイムアウト エラーが発生したりする可能性があります。

重要

プラグインは、実行時間制限とリソース制約に従う必要があります。 詳細情報: プラグイン パフォーマンスの分析

プラグイン コードでの事前バインド型の使用

プラグイン コード内で、事前バインド型を使用することもできます。 プラグイン プロジェクトで生成された型ファイルのみをプロジェクトに含めます。 実行コンテキストの InputParameters コレクションで提供される全てのテーブル タイプは遅延バインド型です。 これらの遅延バインド型を事前バインド型に変換する必要があります。

たとえば、Target パラメーターが取引先企業テーブルを表すことを確認する場合、以下を実行できます。 この例では、「アカウント」が事前バインド型です。

Account acct = context.InputParameters["Target"].ToEntity<Account>();

ただし、事前バインド型を使用して値を設定しないようにする必要があります。 そうすると、SerializationException が発生します。

context.InputParameters["Target"] = new Account() { Name = "MyAccount" }; // WRONG: Do not do this. 

参照

例外処理
プラグインの登録
プラグインのデバッグ
チュートリアル: プラグインを書き込み登録する
プラグインとワークフローの開発に関するベスト プラクティスとガイド

注意

ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)

この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。