开发代码中的自定义活动
来源:广州中睿信息技术有限公司
发布时间:2012/10/21 23:25:16 编辑:admin 阅读 1670

采用自定义活动的好处就在于我们开发的代码段是离散、可分离、可复用的组件。一旦测试成功,我们就可以采用拖放的方法将其添加到任意的工作流中。而CodeActivity的复用仅仅限于在当前的工作流中。

  
  定义Custom Activities
  
  OK,下面开始动手。建立一个名为OrderEntryActivities的Sequential Workflow Console Application工程,然后从Project菜单中选择Add Activity,添加名为ValidateAccountActivity的Activity。一般来说,命名的时候以Activity来结尾,比较规范。 
  
  进入ValidateAccountActivity.cs的代码,把它的基类由SequenceActivity改为Activity,因为这是一个单一的活动,没有必要采用Sequence。
  
  每个自定义的活动都应该设计为独立的组件,它们有自己的输入和输出参数。一个活动并不知道工作流中其它活动的任何信息,只能通过属性值来进行通讯。为了支持绑定,我们采用从属属性(dependency properties)代替常规的.NET属性。此活动所需的从属属性有下面几个:
  
    AccountId:int型,标识待验证的帐号;
  
    IsAccountVerified:bool型,指示AccountId是否有效;
  
    AvailableCredit:decimal型,包含有帐户的信用卡余额
  
  下面的代码就是添加了从属属性之后的ValidateAccountActivity.cs文件。记着在这里可以使用CodeSnippet来快速插入代码。
  
  using System;
  using System.ComponentModel;
  using System.ComponentModel.Design;
  using System.Collections;
  using System.Drawing;
  using System.Workflow.ComponentModel;
  using System.Workflow.ComponentModel.Design;
  using System.Workflow.ComponentModel.Compiler;
  using System.Workflow.ComponentModel.Serialization;
  using System.Workflow.Runtime;
  using System.Workflow.Activities;
  using System.Workflow.Activities.Rules; 
  namespace OrderEntryActivities
  {
  public partial class ValidateAccountActivity: Activity
  {
  public ValidateAccountActivity()
  {
  InitializeComponent();
  }
  #region Public workflow properties
  public static DependencyProperty AccountIdProperty = DependencyProperty.Register("AccountId", typeof(int), typeof(ValidateAccountActivity));
  [DescriptionAttribute("AccountId")]
  [CategoryAttribute("AccountId Category")]
  [BrowsableAttribute(true)]
  [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
  public int AccountId
  {
  get
  {
  return ((int)(base.GetValue(ValidateAccountActivity.AccountIdProperty)));
  }
  set
  {
  base.SetValue(ValidateAccountActivity.AccountIdProperty, value);
  }
  }
  public static DependencyProperty AvailableCreditProperty = DependencyProperty.Register("AvailableCredit", typeof(int), typeof(ValidateAccountActivity));
  [DescriptionAttribute("AvailableCredit")]
  [CategoryAttribute("AvailableCredit Category")]
  [BrowsableAttribute(true)]
  [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
  public int AvailableCredit
  {
  get
  {
  return ((int)(base.GetValue(ValidateAccountActivity.AvailableCreditProperty)));
  }
  set
  {
  base.SetValue(ValidateAccountActivity.AvailableCreditProperty, value);
  }
  }
  public static DependencyProperty IsAccountVerifiedProperty = DependencyProperty.Register("IsAccountVerified", typeof(bool), typeof(ValidateAccountActivity));
  [DescriptionAttribute("IsAccountVerified")]
  [CategoryAttribute("IsAccountVerified Category")]
  [BrowsableAttribute(true)]
  [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
  public bool IsAccountVerified
  {
  get
  {
  return ((bool)(base.GetValue(ValidateAccountActivity.IsAccountVerifiedProperty)));
  }
  set
  {
  base.SetValue(ValidateAccountActivity.IsAccountVerifiedProperty, value);
  }
  }
  #endregion
  }
  }
  
  属性添加完毕,我们需要实现活动的逻辑。实际执行的逻辑是存放在Execute方法中的。这个方法是由基类提供的虚方法,在我们这个派生类中必须要重载实现。当活动被执行时,这个方法就会被工作流运行时同步调用。模拟查找和验证用户的代码如下所示: 
  
  protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
  {
  switch (AccountId)
  {
  case 1001:
  IsAccountVerified = true;
  AvailableCredit = 100.00M;
  break;
  case 2002:
  IsAccountVerified = true;
  AvailableCredit = 500.00M;
  break;
  default:
  IsAccountVerified = false;
  AvailableCredit = 0;
  break;
  }
  return base.Execute(executionContext);
  }
  同样的道理,我们继续添加商品验证活动ValidateProductActivity以及下单活动EnterOrderActivity,具体实现参见源码。 
  
  现在进入我们最终承载功能的工作流Workflow1.cs代码,首先还是添加从属属性,AccountId和SalesItemId,参见源码。在这个文件中,我们上一种方法里需要添加的私有字段就不复存在了。代码完成之后,请按下F6编译整个工程文件。
  
  切换到设计模式,可以看到在Toolbox中已经有我们自定义的活动了(如果没有,请编译一下工程),如下图所示:
  
  自定义活动
  
  绘制工作流
  
  拖放一个ValidateAccountActivity的实例到工作流中。我们现在需要把该活动的AccountId属性与工作流的对应属性绑定起来。要达到这个目的,切换到该活动的属性窗口,如图:
  
  自定义活动
  
  现在绑定AccountId属性,点击它后面的省略号,打开一个如下所示的绑定对话框。
  
  自定义活动
  
  在这个对话框中,我们可以把工作流或者是别的活动的属性绑定到此活动的属性上。只有从属属性才能实现这种功能。在这个例子中,我们将此活动的AccountId属性绑定到工作流的AccountId上。在运行时,通过Dictionary传递给工作流的属性值也会自动地传递到这个活动来。在这个列表里选中AccountId,点击确定。属性窗口中的另外两个属性,AvailableCredit和IsAccountVerified是活动的输出,现在暂时不需要设置绑定。
  
  现在拖放一个IfEElseActivity到刚才那个活动的下方。这个分支活动将根据validateAccountActivity1的IsAccountVerified属性来确定工作流的走向。左边的分支代表着帐户有效,右侧代表无效。分别将它们重新命名为ifAccountVerified和ifAccountInvalid。
  
  在属性窗口里,设置一个this.validateAccountActivity1.IsAccountVerified==true的Declarative Rule Condition,具体做法就不赘述了。
  
  补完右侧的分支,拖放一个CodeActivity,添加如下代码:
  
  private void codeBadAccountId_ExecuteCode(object sender, EventArgs e)
  {
  Console.WriteLine("AccountId {0} 无效", AccountId);
  }
  
  同样的方法,我们继续往下去补充验证商品以及下单的工作流逻辑。请参阅我提供的源码示例。就在今天,.NET Framework 3.5发布了正式版,经过我的测试,卸载beta2版的Framework 3.5,再安装正式版的之后,VS2008 beta2仍然可以正常运行。现在的示例统统都是在正式版的Framework 3.5下编译测试通过的。
  
  最后完成之后的工作流看起来应该是下面的样子:
  
  自定义活动
  
  然后就是修改Program.cs文件,调用这个工作流了。大部分都可以从上一个示例里照抄,唯一需要改动的就是下面的加粗部分:
  
  public void RunWorkflow(Dictionary<string, object> wfArguments)
  {
  // 创建工作流实例并启动
  WorkflowInstance instance = _workflowRuntime.CreateWorkflow(typeof(OrderEntryActivities.Workflow1), wfArguments);
  instance.Start();
  // 等待工作流完成
  _waitHandle.WaitOne();
  }
  本站技术原创栏目文章均为中睿原创或编译,转载请注明:文章来自中睿,本站保留追究责任的权利。