设备申请审批流程(WF实例)

这个例子在我们的项目中已经实际应用,所以我想叫做实例应该没什么问题。这是一个经典的设备申请审批流程,大家很多时候已经用其他的办法实现过了。本实例包括三个工程:EquipmentApply(设备申请exe)、EquipmentApprove(设备审批exe)、EquipmentApplyWorkflowLib(申请审批流程库dll)。首先新建Windows应用程序项目EquipmentApply,界面如图所示:

设备申请审批流程(WF实例)

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="[email protected]@[email protected]@[email protected]@[email protected]@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 415.5pt; HEIGHT: 290.25pt" type="#_x0000_t75"><imagedata src="file:///C:%5CUsers%5Cljc%5CAppData%5CLocal%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.png" o:title=""></imagedata></shape>

添加Windows应用程序项目EquipmentApprove,界面如图所示:

设备申请审批流程(WF实例)

<shape id="_x0000_i1026" style="WIDTH: 357pt; HEIGHT: 343.5pt" type="#_x0000_t75"><imagedata src="file:///C:%5CUsers%5Cljc%5CAppData%5CLocal%5CTemp%5Cmsohtml1%5C01%5Cclip_image003.png" o:title=""><font size="3"></font></imagedata></shape>

添加Workflow中的Sequential Workflow Library项目EquipmentApplyWorkflowLib,建立流程图:

设备申请审批流程(WF实例)

<shape id="_x0000_i1027" style="WIDTH: 403.5pt; HEIGHT: 426.75pt" type="#_x0000_t75"><imagedata src="file:///C:%5CUsers%5Cljc%5CAppData%5CLocal%5CTemp%5Cmsohtml1%5C01%5Cclip_image005.png" o:title=""><font size="3"></font></imagedata></shape>

该流程包括三个外部方法ActivitiesCreateApplyApproveApplyEscalateApply)和两个外部事件ActivitiesEquipmentApproveApplyEscalated),一个ListenActivity用于等待外部事件来重新唤起流程。这里头有几个关键的技术点:

(1) 怎么传递流程参数?启动流程实例时把参数装载到Dictionary中作为CreateWorkflow方法的参数传递:

// Fill the Parameters collection for this instance of the workflow

Dictionary<string, object> parameters = new Dictionary<string, object>();

parameters.Add("CreatedBy", txtCreatedBy.Text);

parameters.Add("EquipmentName", txtName.Text);

parameters.Add("Numbers",StrToInt(txtNumbers.Text));

parameters.Add("Moneys", StrToFloat(txtMoneys.Text));

parameters.Add("Desc", txtDesc.Text);

// Get the type of the workflow

Type type = typeof(EquipmentApplyWorkflowLib.EquipmentApplyWorkflow);

// Start the workflow instance

WorkflowInstance inst = theWorkflowRuntime.CreateWorkflow(type, parameters);

inst.Start();

获取参数是在流程文件中建立相同名称的属性,流程中就可以得到这些参数:

#region 属性

private string m_EquipmentName = "";

public string EquipmentName

{

get { return m_EquipmentName; }

set { m_EquipmentName = value; }

}

private int m_Numbers = 0;

public int Numbers

{

get { return m_Numbers; }

set { m_Numbers = value; }

}

private float m_Moneys = 0;

public float Moneys

{

get { return m_Moneys; }

set { m_Moneys = value; }

}

private string m_Desc = "";

public string Desc

{

get { return m_Desc; }

set { m_Desc = value; }

}

private string m_CreatedBy = "";

public string CreatedBy

{

get { return m_CreatedBy; }

set { m_CreatedBy = value; }

}

#endregion

(2) 怎么持久化流程?需要在初始化流程运行时的时候增加增加其久化服务:

// Add system SQL Persistence service

SqlWorkflowPersistenceService persistenceService = new SqlWorkflowPersistenceService(

"Initial Catalog=PersistenceStore;" +

"Data Source=localhost\\SQLExpress; Integrated Security=SSPI");

wr.AddService(persistenceService);

还需要增加空闲时事件:

wr.WorkflowIdled += new EventHandler<WorkflowEventArgs>(wr_WorkflowIdled);

下面的代码表示在流程空闲时持久化(事实上是保存到数据库,也可以包括到文件,你也可以随时持久化流程)。

void wr_WorkflowIdled(object sender, WorkflowEventArgs e)

{

ThreadPool.QueueUserWorkItem(UnloadInstance, e.WorkflowInstance);

}

static void UnloadInstance(object workflowInstance)

{

((WorkflowInstance)workflowInstance).TryUnload();

}

(3) 怎么增加自定义的服务?需要增加服务接口和参数类:

[Serializable]

public class EquipmentApplyEventArgs : ExternalDataEventArgs

{

private string _operatorName;

public EquipmentApplyEventArgs(Guid InstanceID, string operatorName)

: base(InstanceID)

{

_operatorName = operatorName;

}

public string OperatorName

{

get { return _operatorName; }

set { _operatorName = value; }

}

}

[ExternalDataExchange]

public interface IEquipmentApplyService

{

event EventHandler<EquipmentApplyEventArgs> EquipmentApplyApproved;

event EventHandler<EquipmentApplyEventArgs> EquipmentApplyEscalated;

void CreateEquipmentApply(string name, int numbers, float moneys, string description, string createdBy);

void ApproveEquipmentApply(Guid applyID);

void EscalateEquipmentApply(Guid applyID);

}

[ExternalDataExchange]对于服务接口是必要的声明,否则不能把服务增加到流程中。增加一个类实现这个接口:

public class EquipmentApplyService: IEquipmentApplyService

{

// Implement events

public event EventHandler<EquipmentApplyEventArgs> EquipmentApplyApproved;

public event EventHandler<EquipmentApplyEventArgs> EquipmentApplyEscalated;

public void RaiseApproveEquipmentApplyEvent(Guid instanceId)

{

// Raise the event to the workflow

ThreadPool.QueueUserWorkItem(JustApproveTheEquipmentApply,

new EquipmentApplyEventArgs(instanceId, "ljc"));

}

public void JustApproveTheEquipmentApply(object o)

{

EquipmentApplyEventArgs args = o as EquipmentApplyEventArgs;

if (EquipmentApplyApproved != null)

EquipmentApplyApproved(null, args);

else

{

System.Windows.Forms.MessageBox.Show("设备申请审批为空");

}

}

public void RaiseEscalateEquipmentApplyEvent(Guid instanceId)

{

// Raise the event to the workflow

ThreadPool.QueueUserWorkItem(JustEscalateTheEquipmentApply,

new EquipmentApplyEventArgs(instanceId, "ljc"));

}

public void JustEscalateTheEquipmentApply(object o)

{

EquipmentApplyEventArgs args = o as EquipmentApplyEventArgs;

if (EquipmentApplyEscalated != null)

EquipmentApplyEscalated(null, args);

else

{

System.Windows.Forms.MessageBox.Show("设备申请呈送上级领导为空");

}

}

#region IEquipmentApplyService

void IEquipmentApplyService.CreateEquipmentApply(string name, int numbers, float moneys, string description, string createdBy)

{

// Fill up a EquipmentApply: same ID as the workflow

string applyID = WorkflowEnvironment.WorkflowInstanceId.ToString();

// Create EquipmentApply on the DB

EquipmentApplyRule.CreateEquipmentApply(applyID,name,numbers,moneys, description, createdBy);

}

void IEquipmentApplyService.ApproveEquipmentApply(Guid applyID)

{

// Update EquipmentApply on the DB

EquipmentApplyRule.UpdateEquipmentApply(WorkflowEnvironment.WorkflowInstanceId.ToString(), EquipmentApplyStatus.Approved);

}

void IEquipmentApplyService.EscalateEquipmentApply(Guid applyID)

{

// Update EquipmentApply on the DB

EquipmentApplyRule.UpdateEquipmentApply(WorkflowEnvironment.WorkflowInstanceId.ToString(), EquipmentApplyStatus.Escalated);

}

#endregion

}

在初始化流程运行时的时候就可以把服务增加进来:

// Add the external data service

ExternalDataExchangeService dataService = new ExternalDataExchangeService();

wr.AddService(dataService);

// Add custom EquipmentApply service

theApplyService = new EquipmentApplyService();

dataService.AddService(theApplyService);