示例将模拟对两个整型数字的加、减、乘、除计算器的功能,其中计算的功能将被作为一个自定义活动进行开发,然后在工作流中进行使用。
(1) 创建自定义活动
创建一个“Workflow Activity Library”类型的自定义活动项目,然后使它继承“System.Workflow.ComponentModel.Activity”父类。由于示例是模拟两个整型变量“Para1”和“Para2”之间的数学运算,因此需要分别定义两个“int”类型的属性,以及定义一个“String”类型属性代表运算符“Operator”,代码如下所示。
public static DependencyProperty Para1Property = DependencyProperty.Register("Para1", typeof(System.Int32), typeof(Activity1), new PropertyMetadata(0));
public static DependencyProperty Para2Property = DependencyProperty.Register("Para2", typeof(System.Int32), typeof(Activity1), new PropertyMetadata(10));
public static DependencyProperty OperatorProperty = DependencyProperty.Register("Operator", typeof(System.String), typeof(Activity1), new PropertyMetadata("+"));
[Description("运算符")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string Operator
{
get
{
return ((string)(base.GetValue(Activity1.OperatorProperty)));
}
set
{
base.SetValue(Activity1.OperatorProperty, value);
}
}
[Description("整型数字")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Para1
{
get
{
return ((int)(base.GetValue(Activity1.Para1Property)));
}
set
{
base.SetValue(Activity1.Para1Property, value);
}
}
[Description("整型数字")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Para2
{
get
{
return ((int)(base.GetValue(Activity1.Para2Property)));
}
set
{
base.SetValue(Activity1.Para2Property, value);
}
}
示例还需要一个事件类型属性“Invoked”,用户可以根据该属性创建相应的事件,并将其运算结果显示出来。
public static DependencyProperty InvokedEvent = DependencyProperty.Register("Invoked", typeof(EventHandler<CustomActivityEventArgs>), typeof(Activity1));
public event EventHandler<CustomActivityEventArgs> Invoked
{
add
{
base.AddHandler(Activity1.InvokedEvent, value);
}
remove
{
base.RemoveHandler(Activity1.InvokedEvent, value);
}
}
在定义“Invoked”事件类型属性时,事件的参数使用的是自定义类型“CustomActivityEventArgs”。在使用该自定义活动时,用户可以在该属性创建的事件中,通过参数“e”得到更多的自定义信息。自定义的参数类型代码如下:
public class CustomActivityEventArgs : EventArgs
{
private string result;
public string Result
{
get { return result; }
set { result = value; }
}
}
最后还需要重载“Execute”方法,在该方法中进行数学运算,并加载事件类型的属性“InvokedEvent”,其代码如下
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
CustomActivityEventArgs e = new CustomActivityEventArgs();
if (Operator == "+")
e.Result = (this.Para1 + this.Para2).ToString();
else if (Operator == "-")
e.Result = (this.Para1 - this.Para2).ToString();
else if (Operator == "*")
e.Result = (this.Para1 * this.Para2).ToString();
else if (Operator == "/")
e.Result = (this.Para1 / this.Para2).ToString();
this.RaiseGenericEvent<CustomActivityEventArgs>(InvokedEvent, this, e);
return ActivityExecutionStatus.Closed;
}
由于示例进行的是数学运算,为防止发生“除数为0”的异常情况,还需要为自定义活动的属性值增加验证判断。
public class CustomActivityValidator : System.Workflow.ComponentModel.Compiler.ActivityValidator
{
public override ValidationErrorCollection ValidateProperties(ValidationManager manager, object obj)
{
ValidationErrorCollection validationErrors = base.ValidateProperties(manager, obj);
Activity1 activity = obj as Activity1;
if (activity != null)
{
if (string.IsNullOrEmpty(activity.Operator))
{
validationErrors.Add(ValidationError.GetNotSetValidationError(Activity1.OperatorProperty.Name));
}
if (activity.Para2 == 0)
{
validationErrors.Add(new ValidationError("除数不能为0", 1, false, Activity1.Para2Property.Name));
}
}
return validationErrors;
}
}
(2)创建工作流项目
创建一个顺序类型工作流项目,将该自定义活动拖入到工作流设计界面,在工作流“workflow1.cs”文件中添加以下3个属性,如图1所示,分别将它与自定义活动的3个属性进行绑定。
private string oper;
public string Oper
{
get { return oper; }
set { oper = value; }
}
private int para1;
public int Para1
{
get { return para1; }
set { para1 = value; }
}
private int para2;
public int Para2
{
get { return para2; }
set { para2 = value; }
}
图1 自定义活动示例工作流界面
最后通过“Invoked”属性创建一个用于执行的事件,用户可以通过该事件“CustomActivityEventArgs”类型的参数“e”得到运算结果的返回值,并将它显示出来
private void activity11_Invoked(object sender, ActivityLibrary4.CustomActivityEventArgs e)
{
MessageBox.Show(e.Result);
}
(3)创建应用程序项目
创建一个Windows应用程序项目,其界面如图2所示,用户可以选择所需的运算符,输入两个整型数字,点击“计算”按钮进行相应的数学运算。在“计算”按钮中用户会将界面上的运算符和两个整型数字作为参数传递给工作流项目,由于工作流文件中定义的3个属性已经与自定义活动相绑定,因此界面上用户操作的信息就直接传递给了自定义活动。应用程序“计算”按钮的代码如下所示。
private void button1_Click(object sender, EventArgs e)
{
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("Oper", this.comboBox1.Text);
parameters.Add("Para1", Convert.ToInt32(textBox1.Text));
parameters.Add("Para2", Convert.ToInt32(textBox2.Text));
wfInstance=wfRuntime.CreateWorkflow(typeof(Workflow1),parameters);
wfInstance.Start();
}