宣言の制約Declarative Constraints

宣言の制約には、アクティビティ、およびそのアクティビティと他のアクティビティとの関係に関する検証の強力なメソッドが用意されています。Declarative constraints provide a powerful method of validation for an activity and its relationships with other activities. アクティビティに関する制約はプロセスの作成中に構成されますが、ワークフロー ホストによって追加の制約を指定することもできます。Constraints are configured for an activity during the authoring process, but additional constraints can also be specified by the workflow host. ここでは、宣言の制約を使用してアクティビティを検証する方法の概要について説明します。This topic provides an overview of using declarative constraints to provide activity validation.

宣言の制約の使用Using Declarative Constraints

制約とは、検証ロジックを含むアクティビティです。A constraint is an activity that contains validation logic. この制約アクティビティは、コードまたは XAML で作成できます。This constraint activity can be authored in code or in XAML. 制約アクティビティを作成したら、アクティビティの作成者はアクティビティの Constraints プロパティにこの制約を追加して検証を実行します。またはこの制約を使用して、AdditionalConstraints インスタンスの ValidationSettings プロパティを使った追加の検証を実行します。After a constraint activity is created, activity authors add this constraint to the Constraints property of the activity to validate, or they use the constraint to provide additional validation by using the AdditionalConstraints property of a ValidationSettings instance. 検証ロジックは、アクティビティのメタデータの検証など、単純な検証で構成されますが、親アクティビティ、子アクティビティ、および兄弟アクティビティに対する現在のアクティビティの関係を考慮した検証を実行することもできます。The validation logic can consist of simple validations such as validating an activity’s metadata, but it can also perform validation that takes into account the relationship of the current activity to its parent, children, and sibling activities. 制約は、Constraint<T> アクティビティを使用して作成されます。また、検証のエラーと警告の作成を補助し、ワークフロー内の関連するアクティビティに関する情報を提供する追加の検証アクティビティがいくつか用意されています。Constraints are authored by using the Constraint<T> activity, and several additional validation activities are provided to assist with the creation of validation errors and warnings and to provide information about related activities in the workflow.

AssertValidation と AddValidationErrorAssertValidation and AddValidationError

AssertValidation アクティビティは、その Assertion プロパティから参照される式を評価します。また、式が false に評価されると、検証のエラーまたは警告が ValidationResults に追加されます。The AssertValidation activity evaluates the expression referenced by its Assertion property, and if the expression evaluates to false, a validation error or warning is added to the ValidationResults. Message プロパティは検証エラーを示し、IsWarning は検証の失敗がエラーか警告かを指定します。The Message property describes the validation error and the IsWarning property indicates whether the validation failure is an error or a warning. IsWarning の既定値は false です。The default value for IsWarning is false.

次の例では、検証対象のアクティビティの DisplayName が 2 文字以下の場合、検証の警告を返す制約を宣言します。In the following example, a constraint is declared that returns a validation warning if the DisplayName of the activity being validated is two characters or less in length. Constraint<T> に使用されるジェネリック型パラメーターには、この制約によって検証されるアクティビティの型を指定します。The generic type parameter used for Constraint<T> specifies the type of activity that is validated by the constraint. この制約では、ジェネリック型として Activity を使用します。この制約はすべての種類のアクティビティに使用できます。This constraint uses Activity as the generic type and can be used to validate all types of activities.

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 に追加します。To specify this constraint for an activity, it is added to the Constraints of the activity, as shown in the following example code.

public sealed class SampleActivity : CodeActivity  
{  
    public SampleActivity()  
    {  
        base.Constraints.Add(ActivityDisplayNameIsNotSetWarning());  
    }  
  
    // Activity implementation omitted.  
}  

また、ホストは AdditionalConstraints を使用してワークフローでアクティビティの制約を指定することもできます。この方法については、次のセクションで説明します。The host could also specify this constraint for activities in a workflow by using AdditionalConstraints, which is covered in the next section.

AddValidationError アクティビティは、式を評価せずに、検証のエラーまたは警告を生成するために使用されます。The AddValidationError activity is used to generate a validation error or warning without requiring the evaluation of an expression. このプロパティは AssertValidation に似ており、If アクティビティなど、制約のフロー コントロール アクティビティと併用できます。Its properties are similar to AssertValidation and it can be used in conjunction with flow control activities of a constraint such as the If activity.

ワークフロー関係のアクティビティWorkflow Relationship Activities

複数の検証アクティビティが使用できます。これにより検証されるアクティビティに関連してワークフロー内の他のアクティビティに関する情報が提供されます。Several validation activities are available that provide information about the other activities in the workflow in relation to the activity being validated. GetParentChain は現在のアクティビティとルート アクティビティ間のすべてのアクティビティを含むアクティビティのコレクションを返します。GetParentChain returns a collection of activities that contains all of the activities between the current activity and the root activity. GetChildSubtree は再帰パターンで子アクティビティを含むアクティビティのコレクションを提供し、GetWorkflowTree はワークフロー中のすべてのアクティビティを取得します。GetChildSubtree provides a collection of activities that contains the child activities in a recursive pattern, and GetWorkflowTree gets all the activities in the workflow.

次の例では、 CreateState アクティビティを定義します。In the following example, a CreateState activity is defined. CreateState アクティビティは CreateCountry アクティビティ内に含まれる必要があり、GetParent メソッドはこの要件を強制する制約を返します。The CreateState activity must be contained within a CreateCountry activity, and the GetParent method returns a constraint that enforces this requirement. GetParentGetParentChain アクティビティを ForEach<T> アクティビティと組み合わせて使用し、CreateState のアクティビティの親アクティビティを確認し、要件を満たしているかどうか判断します。GetParent uses the GetParentChain activity in conjunction with a ForEach<T> activity to inspect the parent activities of the CreateState activity to determine if the requirement is met.

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  
    }  
}  

追加の制約Additional Constraints

ワークフロー ホスト作成者は、ワークフロー内のアクティビティに追加の検証の制約を指定できます。この場合、制約を作成し、それを AdditionalConstraints インスタンスの ValidationSettings ディクショナリに追加します。Workflow host authors can specify additional validation constraints for activities in a workflow by creating constraints and adding them to the AdditionalConstraints dictionary of a ValidationSettings instance. AdditionalConstraints の各アイテムには、制約の適用対象であるアクティビティの種類と、その種類のアクティビティに対する追加の制約一覧が含まれます。Each item in AdditionalConstraints contains the type of activity for which the constraints apply and a list of the additional constraints for that type of activity. ワークフローで検証が呼び出されると、派生クラスを含め、指定した種類の各アクティビティは制約を評価します。When validation is invoked for the workflow, each activity of the specified type, including derived classes, evaluates the constraints. この例では、前のセクションの ActivityDisplayNameIsNotSetWarning 制約は、ワークフロー内のすべてのアクティビティに適用されます。In this example, the ActivityDisplayNameIsNotSetWarning constraint from the previous section is applied to all activities in a workflow.

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);  
    }  
}  

OnlyUseAdditionalConstraintsValidationSettings プロパティが true の場合、Validate を呼び出すことで検証が開始されると、指定した追加の制約のみが評価されます。If the OnlyUseAdditionalConstraints property of ValidationSettings is true, then only the specified additional constraints are evaluated when validation is invoked by calling Validate. これは、特定の検証の構成についてワークフローを調べる場合に役立ちます。This can be useful for inspecting workflows for specific validation configurations. ただし、ワークフローを呼び出すときに、ワークフロー内で構成されている検証ロジックが評価され、ワークフローが正常に開始するようにこれに合格する必要があります。Note however that when the workflow is invoked, the validation logic configured in the workflow is evaluated and must pass for the workflow to successfully begin. 検証の呼び出しの詳細については、次を参照してください。アクティビティの検証を呼び出すします。For more information about invoking validation, see Invoking Activity Validation.