在WF3.x时代我们可以使用声明性的条件和代码方式的条件,也可以使用支持正向链接的RuleSet。当然我们还可以使用基于CodeDOM的API来用代码的方式声明。
在微软刚刚发布的WF4.0 Beta1中我们已经看不到这些了,WF4.0提供了统一的完全声明式的表达式(Expression)。现在的版本只支持使用VB来构建表达式(Expression),但是在设计上是可以支持任何语言的,微软也会在未来的版本中提供对其他语言的支持。
WF4.0中表达式是ValueExpression类型的,我们在VS中构造表达式的窗口是ExpressionTextBox类的实例,它也是可以再外部重新宿主的,只不过只有和VS结合的时候才有智能感知和颜色的支持。在表达式中我们可以引用工作流中的变量和参数。这些信息都会被序列化到XAML中。提供了表达式(Expression)并不是就不要原来的方式,微软在开发WF4.0一个很重要的部分就是对WF3.x全面兼容。在WF4.0中提供了一个Interop活动可以帮助我们很好的完成现有WF3.x程序的迁移,我们只需要简单的设置它的Body Type属性即可,我们可以将WF4.0中的变量和参数绑定到WF3.x中的依赖属性上,如下图:
在WF4.0 beta1中没有提供对正向链接的RuleSet功能,官方已经声明会在将来的版本中加大这部分的投入。现在如果我们要想在WF4.0 Beta1使用类似的功能我们可以开发一个自定义活动来完成,下面的例子来源于WF Samples中,首先是活动的代码部分:
namespace Microsoft.Samples.Rules
{
using System;
using System.Activities;
using System.ComponentModel;
using System.Workflow.Activities.Rules;
using System.Workflow.ComponentModel.Compiler;
[Designer(typeof(Microsoft.Samples.Rules.PolicyDesigner))]
public sealed class Policy40Activity : NativeActivity
{
public RuleSet RuleSet { get; set; }
[IsRequired]
public InOutArgument TargetObject { get; set; }
public OutArgument<ValidationErrorCollection> ValidationErrors { get; set; }
protected override void OnOpen(DeclaredEnvironment environment)
{
if (this.RuleSet == null)
{
throw new System.ArgumentNullException("RuleSet property can't be null");
}
}
protected override void Execute(ActivityExecutionContext context)
{
// validate before running
Type targetType = this.TargetObject.Get(context).GetType();
RuleValidation validation = new RuleValidation(targetType, null);
if (!this.RuleSet.Validate(validation))
{
// set the validation error out argument
this.ValidationErrors.Set(context, validation.Errors);
// throw a validation exception
throw new ValidationException(string.Format("The ruleset is not valid. {0} validation errors found (check the ValidationErrors property for more information).", validation.Errors.Count));
}
// execute the ruleset
object evaluatedTarget = this.TargetObject.Get(context);
RuleEngine engine = new RuleEngine(this.RuleSet, validation);
engine.Execute(evaluatedTarget);
// update the target object
this.TargetObject.Set(context, evaluatedTarget);
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
下面是活动的设计器部分,在WF4.0中提供了对活动设计器的可视化支持:
<sad:WorkflowElementDesigner x:Class="Microsoft.Samples.Rules.PolicyDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sad="clr-namespace:System.Activities.Design;assembly=System.Activities.Design"
xmlns:sadv="clr-namespace:System.Activities.Design.View;assembly=System.Activities.Design">
<sad:WorkflowElementDesigner.Resources>
<sadv:ArgumentToExpressionConverter x:Uid="sadv:ArgumentToExpressionConverter_1" x:Key="argumentToExpressionConverter" />
</sad:WorkflowElementDesigner.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition x:Uid="RowDefinition_1" />
<RowDefinition x:Uid="RowDefinition_2" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Uid="ColumnDefinition_1" Width="70*" />
<ColumnDefinition x:Uid="ColumnDefinition_2" Width="196*" />
</Grid.ColumnDefinitions>
<Label Content="Target Object" Name="label1" Margin="0,5,0,7"/>
<sadv:ExpressionTextBox
x:Uid="ExpressionTextBox_1"
Grid.Row="0" Grid.Column="1"
AutomationProperties.AutomationId="TargetObject"
Width="190" Margin="9,7,9,7" MaxLines="1"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
Expression="{Binding Path=ModelItem.TargetObject, Mode=TwoWay, Converter={StaticResource argumentToExpressionConverter}, ConverterParameter=InOut}"
UseLocationExpression="True"
OwnerActivity="{Binding Path=ModelItem, Mode=TwoWay}" />
<Button Content="Edit RuleSet" Name="button1" Width="190" Margin="9,9,9,9" Click="button1_Click" Grid.Row="1" Grid.Column="1" />
</Grid>
</sad:WorkflowElementDesigner>
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
效果如下图:
下面是当点击按钮后,会出现RuleSet的编辑器:
using System;
using System.Activities;
using System.Windows;
using System.Windows.Forms;
using System.Workflow.Activities.Rules;
using System.Workflow.Activities.Rules.Design;
namespace Microsoft.Samples.Rules
{
// Interaction logic for PolicyDesigner.xaml
public partial class PolicyDesigner
{
public PolicyDesigner()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
// verifiy that TargetObject property has been configured
object targetObject = ModelItem.Properties["TargetObject"].ComputedValue;
if (targetObject == null)
{
System.Windows.MessageBox.Show("TargetObject needs to be configured before adding the rules");
return;
}
// verify that target object is correctly configured
InOutArgument arg = targetObject as InOutArgument;
if (arg == null)
{
System.Windows.MessageBox.Show("Invalid target object");
return;
}
// open the ruleset editor
Type targetObjectType = arg.ArgumentType;
RuleSet ruleSet = ModelItem.Properties["RuleSet"].ComputedValue as RuleSet;
if (ruleSet == null)
ruleSet = new RuleSet();
RuleSetDialog ruleSetDialog = new RuleSetDialog(targetObjectType, null, ruleSet);
DialogResult result = ruleSetDialog.ShowDialog();
// update the model item
if (result == DialogResult.OK) {
ModelItem.Properties["RuleSet"].SetValue(ruleSetDialog.RuleSet);
}
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
这样我们就可以再WF4.0中使用该活动了,如下图:
【编辑推荐】