このトピックの内容は、Windows Workflow Foundation 4 に該当します。
宣言の制約には、アクティビティ、およびそのアクティビティと他のアクティビティとの関係に関する検証の強力なメソッドが用意されています。アクティビティに関する制約はプロセスの作成中に構成されますが、ワークフロー ホストによって追加の制約を指定することもできます。ここでは、宣言の制約を使用してアクティビティを検証する方法の概要について説明します。
宣言の制約の使用
制約とは、検証ロジックを含むアクティビティです。この制約アクティビティは、コードまたは XAML で作成できます。制約アクティビティを作成したら、アクティビティの作成者はアクティビティの Constraints プロパティにこの制約を追加して検証を実行します。またはこの制約を使用して、ValidationSettings インスタンスの AdditionalConstraints プロパティを使った追加の検証を実行します。検証ロジックは、アクティビティのメタデータの検証など、単純な検証で構成されますが、親アクティビティ、子アクティビティ、および兄弟アクティビティに対する現在のアクティビティの関係を考慮した検証を実行することもできます。制約は、Constraint アクティビティを使用して作成されます。また、検証のエラーと警告の作成を補助し、ワークフロー内の関連するアクティビティに関する情報を提供する追加の検証アクティビティがいくつか用意されています。
AssertValidation と AddValidationError
AssertValidation アクティビティは、その Assertion から参照される式を評価します。また、式が false に評価されると、検証のエラーまたは警告が ValidationResults に追加されます。Message プロパティは検証エラーを示し、IsWarning は検証の失敗がエラーか警告かを指定します。IsWarning の既定値は false です。
次の例では、検証対象のアクティビティの DisplayName が 2 文字以下の場合、検証の警告を返す制約を宣言します。Constraint に使用されるジェネリック型パラメーターには、この制約によって検証されるアクティビティの型を指定します。この制約では、ジェネリック型として Activity を使用します。この制約はすべての種類のアクティビティに使用できます。
public static Constraint ActivityDisplayNameIsNotSetWarning()
{
DelegateInArgument<Activity> element = new DelegateInArgument<Activity>();
return new Constraint<Activity>
{
Body = new ActivityAction<Activity, ValidationContext>
{
Argument1 = element,
Handler = new AssertValidation
{
IsWarning = true,
Assertion = new InArgument<bool>(env => (element.Get(env).DisplayName.Length > 2)),
Message = new InArgument<string>("It is a best practice to have a DisplayName of more than 2 characters."),
}
}
};
}
あるアクティビティに対してこの制約を指定するには、次のコード例のように、アクティビティの Constraints に追加します。
public sealed class SampleActivity : CodeActivity
{
public SampleActivity()
{
base.Constraints.Add(ActivityDisplayNameIsNotSetWarning ());
}
// Activity implementation omitted.
}
また、この制約は、ホストで AdditionalConstraints をすることによって、ワークフローのアクティビティに指定することもできます。この方法については、次のセクションで説明します。
AddValidationError アクティビティは、式を評価せずに、検証のエラーまたは警告を生成するために使用されます。このプロパティは AssertValidation に似ており、If アクティビティなど、制約のフロー コントロール アクティビティと併用できます。
ワークフロー関係のアクティビティ
いくつかの検証アクティビティには、検証対象のアクティビティと関係があるワークフロー内の他のアクティビティに関する情報を提供する機能があります。GetParentChain は、現在のアクティビティとルート アクティビティ間にあるすべてのアクティビティを含むアクティビティのコレクションを返します。GetChildSubtree は、再帰的パターンで子のアクティビティを含むアクティビティのコレクションを提供します。GetWorkflowTree は、ワークフロー内のすべてのアクティビティを取得します。
ContainmentValidation サンプルの次の例では、CreateState
アクティビティが定義されます。CreateState
アクティビティは CreateCountry
アクティビティに含める必要があります。また、GetParent
メソッドは、この要件を強制する制約を返します。GetParent
は GetParentChain アクティビティと ForEach アクティビティを併用して、CreateState
アクティビティの親アクティビティを調べ、要件を満たしているかどうかを判断します。
public sealed class CreateState : CodeActivity
{
public CreateState()
{
base.Constraints.Add(CheckParent());
this.Cities = new List<Activity>();
}
public List<Activity> Cities { get; set; }
public string Name { get; set; }
static Constraint CheckParent()
{
DelegateInArgument<CreateState> element = new DelegateInArgument<CreateState>();
DelegateInArgument<ValidationContext> context = new DelegateInArgument<ValidationContext>();
Variable<bool> result = new Variable<bool>();
DelegateInArgument<Activity> parent = new DelegateInArgument<Activity>();
return new Constraint<CreateState>
{
Body = new ActivityAction<CreateState,ValidationContext>
{
Argument1 = element,
Argument2 = context,
Handler = new Sequence
{
Variables =
{
result
},
Activities =
{
new ForEach<Activity>
{
Values = new GetParentChain
{
ValidationContext = context
},
Body = new ActivityAction<Activity>
{
Argument = parent,
Handler = new If()
{
Condition = new InArgument<bool>((env) => object.Equals(parent.Get(env).GetType(),typeof(CreateCountry))),
Then = new Assign<bool>
{
Value = true,
To = result
}
}
}
},
new AssertValidation
{
Assertion = new InArgument<bool>(result),
Message = new InArgument<string> ("CreateState has to be inside a CreateCountry activity"),
}
}
}
}
};
}
protected override void Execute(CodeActivityContext context)
{
// not needed for the sample
}
}
詳細については、次のトピックを参照してください。、Windows Workflow Foundation の 検証 サンプルを参照してください。
追加の制約
ワークフロー ホスト作成者は、ワークフロー内のアクティビティに追加の検証の制約を指定できます。この場合、制約を作成し、それを ValidationSettings インスタンスの AdditionalConstraints ディクショナリに追加します。AdditionalConstraints の各アイテムには、制約の適用対象であるアクティビティの種類と、その種類のアクティビティに対する追加の制約一覧が含まれます。ワークフローで検証が呼び出されると、派生クラスを含め、指定した種類の各アクティビティは制約を評価します。この例では、前のセクションの ActivityDisplayNameIsNotSetWarning
制約は、ワークフロー内のすべてのアクティビティに適用されます。
Activity wf = new Sequence
{
// Workflow Details Omitted.
};
ValidationSettings settings = new ValidationSettings()
{
AdditionalConstraints =
{
{typeof(Activity), new List<Constraint> {ActivityDisplayNameIsNotSetWarning()}},
}
};
// Validate the workflow.
ValidationResults results = ActivityValidationServices.Validate(wf, settings);
// Evaluate the results.
if (results.Errors.Count == 0 && results.Warnings.Count == 0)
{
Console.WriteLine("No warnings or errors");
}
else
{
foreach (ValidationError error in results.Errors)
{
Console.WriteLine("Error in " + error.Source.DisplayName + ": " + error.Message);
}
foreach (ValidationError warning in results.Warnings)
{
Console.WriteLine("Warning in " + warning.Source.DisplayName + ": " + warning.Message);
}
}
ValidationSettings の OnlyUseAdditionalConstraints プロパティが true の場合、Validate を呼び出すことで検証が開始されると、指定した追加の制約のみが評価されます。これは、特定の検証の構成についてワークフローを調べる場合に役立ちます。ただし、ワークフローを呼び出すときに、ワークフロー内で構成されている検証ロジックが評価されます。また、ワークフローが正常に開始するように合格する必要があります。検証の呼び出し詳細情報、「アクティビティ検証の呼び出し」を参照してください。