调用活动验证
本主题适用于 Windows Workflow Foundation 4。
活动验证提供了一种在执行任何活动配置之前标识和报告此配置中的错误的方法。当在工作流设计器中修改工作流,并且工作流设计器中显示任何验证错误或警告时,将执行验证。此外,当调用工作流时,如果发生任何验证错误,默认验证逻辑将引发 InvalidWorkflowException,此时,也将在运行时执行验证。工作流应用程序和工具开发人员可使用 Windows Workflow Foundation (WF) 提供的 ActivityValidationServices 类显式验证活动。本主题说明如何使用 ActivityValidationServices 执行活动验证。
使用 ActivityValidationServices
ActivityValidationServices 具有两种 Validate 重载,用于调用活动的验证逻辑。第一种重载采用要验证的根活动,并返回验证错误和警告的集合。下面的示例使用含有两个必需参数的自定义 Add
活动。
public sealed class Add : CodeActivity<int>
{
[RequiredArgument]
public InArgument<int> Operand1 { get; set; }
[RequiredArgument]
public InArgument<int> Operand2 { get; set; }
protected override int Execute(CodeActivityContext context)
{
return Operand1.Get(context) + Operand2.Get(context);
}
}
Add
活动在 Sequence 中使用,但未绑定该活动的两个必需参数,如下面的示例所示。
Variable<int> Operand1 = new Variable<int>{ Default = 10 };
Variable<int> Operand2 = new Variable<int>{ Default = 15 };
Variable<int> Result = new Variable<int>();
Activity wf = new Sequence
{
Variables = { Operand1, Operand2, Result },
Activities =
{
new Add(),
new WriteLine
{
Text = new InArgument<string>(env => "The result is " + Result.Get(env))
}
}
};
此工作流可以通过调用 Validate 进行验证。Validate 返回活动及其所有子级包含的所有验证错误或警告的集合,如下面的示例所示。
ValidationResults results = ActivityValidationServices.Validate(wf);
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: {0}", error.Message);
}
foreach (ValidationError warning in results.Warnings)
{
Console.WriteLine("Warning: {0}", warning.Message);
}
}
注意: |
---|
自定义活动作者可以在活动的 CacheMetadata 重写中提供验证逻辑。由 CacheMetadata 引发的异常不会视为验证错误。这些异常将从对 Validate 的调用中转义,并且必须由调用方进行处理。 |
当对此示例工作流调用 Validate 时,返回两个验证错误。
错误:未提供必要活动参数“Operand2”的值。
错误:未提供必要活动参数“Operand1”的值。
如果已调用此工作流,将引发 InvalidWorkflowException,如下面的示例所示。
try
{
WorkflowInvoker.Invoke(wf);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
System.Activities.InvalidWorkflowException:
在处理工作流树时遇到以下错误:
“Add”:未提供必要活动参数“Operand2”的值。
“Add”:未提供必要活动参数“Operand1”的值。
为使此示例工作流有效,必须绑定 Add
活动的两个必需参数。在下面的示例中,这两个必需参数绑定到工作流变量和结果值。在此示例中,Result 参数与这两个必需参数绑定在一起。不必绑定 Result 参数,因为如果未绑定该参数,并不会导致验证错误。如果在工作流中的其他位置使用 Result 的值,工作流作者应负责绑定该参数。
new Add
{
Operand1 = Operand1,
Operand2 = Operand2,
Result = Result
}
验证根活动中的必需参数
如果工作流的根活动含有实参,则在调用该工作流并向其传递形参之前,不会绑定这些实参,因此,如果已调用工作流但未传入必需实参,下面的工作流将通过验证,但会引发异常,如下面的示例所示。
Activity wf = new Add();
ValidationResults results = ActivityValidationServices.Validate(wf);
// results has no errors or warnings, but when the workflow
// is invoked, an InvalidWorkflowException is thrown.
try
{
WorkflowInvoker.Invoke(wf);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
System.ArgumentException: The root activity's argument settings are incorrect.
Either fix the workflow definition or supply input values to fix these errors:
'Add': Value for a required activity argument 'Operand2' was not supplied.
'Add': Value for a required activity argument 'Operand1' was not supplied.
传递正确的参数之后,工作流将成功完成,如下面的示例所示。
Add wf = new Add();
ValidationResults results = ActivityValidationServices.Validate(wf);
// results has no errors or warnings, and the workflow completes
// successfully because the required arguments were passed.
try
{
Dictionary<string, object> wfparams = new Dictionary<string, object>
{
{ "Operand1", 10 },
{ "Operand2", 15 }
};
int result = WorkflowInvoker.Invoke(wf, wfparams);
Console.WriteLine("Result: {0}", result);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
注意: |
---|
在此示例中,根活动已声明为 Add ,而不是上述示例中的 Activity。这使 WorkflowInvoker.Invoke 方法返回一个表示 Add 活动的结果的整数,而不是 out 参数的字典。也可将 wf 变量声明为 Activity<int> 。
|
当验证根参数时,主机应用程序应负责确保在调用工作流时传递所有必需参数。
使用 ValidationSettings
默认情况下,当 ActivityValidationServices 调用验证时,将计算活动树中的所有活动。ValidationSettings 允许通过配置其三个属性,采用多种不同方法来自定义验证。SingleLevel 指定验证程序是应遍历整个活动树,还是仅向提供的活动应用验证逻辑。该值的默认值为 false。AdditionalConstraints 指定从类型映射到约束列表的其他约束。对于计算的活动树中的每个活动的基类型,将查找 AdditionalConstraints。如果找到匹配的约束列表,则会针对活动计算该列表中的所有约束。OnlyUseAdditionalConstraints 指定验证程序是应计算所有约束还是仅计算 AdditionalConstraints 中指定的约束。默认值为 false。AdditionalConstraints 和 OnlyUseAdditionalConstraints 有助于工作流主机作者为工作流添加其他验证,例如,适用于 FxCop 等工具的策略约束。有关约束的更多信息,请参见声明性约束。
若要使用 ValidationSettings,请配置所需属性,然后在调用 Validate 时传递这些属性。在此示例中,将验证由包含自定义 Add
活动的 Sequence 组成的工作流。Add
活动具有两个必需参数。
public sealed class Add : CodeActivity<int>
{
[RequiredArgument]
public InArgument<int> Operand1 { get; set; }
[RequiredArgument]
public InArgument<int> Operand2 { get; set; }
protected override int Execute(CodeActivityContext context)
{
return Operand1.Get(context) + Operand2.Get(context);
}
}
下面的 Add
活动在 Sequence 中使用,但未绑定该活动的两个必需参数。
Variable<int> Operand1 = new Variable<int> { Default = 10 };
Variable<int> Operand2 = new Variable<int> { Default = 15 };
Variable<int> Result = new Variable<int>();
Activity wf = new Sequence
{
Variables = { Operand1, Operand2, Result },
Activities =
{
new Add(),
new WriteLine
{
Text = new InArgument<string>(env => "The result is " + Result.Get(env))
}
}
};
在下面的示例中,将执行验证,并将 SingleLevel 设置为 true,以便仅验证 Sequence 根活动。
ValidationSettings settings = new ValidationSettings
{
SingleLevel = true
};
ValidationResults results = ActivityValidationServices.Validate(wf, settings);
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: {0}", error.Message);
}
foreach (ValidationError warning in results.Warnings)
{
Console.WriteLine("Warning: {0}", warning.Message);
}
}
此代码显示以下输出内容。
没有警告或错误
尽管未绑定 Add
活动的必需参数,但验证仍成功完成,这是因为仅计算了根活动。此验证类型对于只验证活动树中的特定元素非常有用,例如,在设计器中验证单个活动的属性更改。请注意,如果将调用此工作流,将计算在工作流中配置的完全验证,并且将引发 InvalidWorkflowException。ActivityValidationServices 和 ValidationSettings 仅配置主机显式调用的验证,而不会配置在调用工作流时所执行的验证。