次の方法で共有


アクティビティ ツリー検査

このトピックの内容は、Windows Workflow Foundation 4 に該当します。

アクティビティ ツリー検査は、アプリケーションによってホストされるワークフローを検査するためにワークフロー アプリケーションの作成者によって使用されます。WorkflowInspectionServices を使用することによって、特定の子アクティビティを対象としてワークフローを検索したり、個々のアクティビティとそのプロパティを列挙したりできるほか、アクティビティのランタイム メタデータを特定の時点でキャッシュできます。ここでは、WorkflowInspectionServices の概要を説明します。また、これを使用してアクティビティ ツリーを検査する方法も説明します。

WorkflowInspectionServices の使用

GetActivities メソッドは、指定したアクティビティ ツリーのアクティビティをすべて列挙するために使用されます。GetActivities は、子、デリゲート ハンドラー、変数の既定値、引数の式を含む、ツリー内のすべてのアクティビティに接触する列挙可能なアクティビティを返します。次の例では、ワークフロー定義は SequenceWhileForEachWriteLine、および式を使用して作成されます。ワークフロー定義が作成されると、このワークフロー定義が呼び出されて、InspectActivity メソッドが呼び出されます。

Variable<List<string>> items = new Variable<List<string>>
{
    Default = new VisualBasicValue<List<string>>("New List(Of String)()")
};

DelegateInArgument<string> item = new DelegateInArgument<string>();

Activity wf = new Sequence
{
    Variables = { items },
    Activities =
    {
        new While((env) => items.Get(env).Count < 5)
        {
            Body = new AddToCollection<string>
            {
                Collection = new InArgument<ICollection<string>>(items),
                Item = new InArgument<string>((env) => "List Item " + (items.Get(env).Count + 1))
            }
        },
        new ForEach<string>
        {
            Values = new InArgument<IEnumerable<string>>(items),
            Body = new ActivityAction<string>
            {
                Argument = item,
                Handler = new WriteLine
                {
                    Text = item
                }
            }
        },
        new Sequence
        {
            Activities = 
            {
                new WriteLine
                {
                    Text = "Items added to collection."
                }
            }
        }
    }
};

WorkflowInvoker.Invoke(wf);

InspectActivity(wf, 0);

アクティビティを列挙するために、GetActivities がルート アクティビティで呼び出され、返される各アクティビティでもう一度再帰的に呼び出されます。次の例では、アクティビティ ツリーのそれぞれのアクティビティと式の DisplayName がコンソールに書き込まれます。

static void InspectActivity(Activity root, int indent)
{
    // Inspect the activity tree using WorkflowInspectionServices.
    IEnumerator<Activity> activities = 
        WorkflowInspectionServices.GetActivities(root).GetEnumerator();

    Console.WriteLine("{0}{1}", new string(' ', indent), root.DisplayName);

    while (activities.MoveNext())
    {
        InspectActivity(activities.Current, indent + 2);
    }
}

このサンプル コードから次の出力が得られます。

リスト項目 1
リスト項目 2
リスト項目 3
リスト項目 4
リスト項目 5
コレクションに追加する項目。
Sequence
  Literal<List<String>>
  While
    AddToCollection<String>
      VariableValue<ICollection<String>>
      LambdaValue<String>
        LocationReferenceValue<List<String>>
    LambdaValue<Boolean>
      LocationReferenceValue<List<String>>
  ForEach<String>
    VariableValue<IEnumerable<String>>
    WriteLine
      DelegateArgumentValue<String>
  Sequence
    WriteLine
      Literal<String>

すべてのアクティビティを列挙するのではなく、特定のアクティビティを取得する場合は、Resolve を使用します。ResolveGetActivities はいずれも、WorkflowInspectionServices.CacheMetadata が前に呼び出されていない場合にメタデータのキャッシュ処理を実行します。CacheMetadata が呼び出されている場合、GetActivities は既存のメタデータに基づいています。このため、CacheMetadata を最後に呼び出した後でツリーが変更されていると、予期しない結果が GetActivities で生じることがあります。GetActivities を呼び出した後にワークフローに変更を加えた場合は、ActivityValidationServices Validate メソッドを呼び出して、メタデータを再キャッシュすることができます。メタデータのキャッシュ処理については、次のセクションで説明します。

メタデータのキャッシュ処理

アクティビティのメタデータをキャッシュすると、アクティビティの引数、変数、子アクティビティ、アクティビティ デリゲートの記述が構築および検証されます。既定では、メタデータはアクティビティが実行用に準備されるときにランタイムによってキャッシュされます。ワークフロー ホストの作成者が、それよりも前 (すべてのコストを先に取得する場合など) にアクティビティまたはアクティビティ ツリーのメタデータをキャッシュする場合は、CacheMetadata を使用して目的の時点でメタデータをキャッシュできます。