设备申请审批流程(WF实例)
这个例子在我们的项目中已经实际应用,所以我想叫做实例应该没什么问题。这是一个经典的设备申请审批流程,大家很多时候已经用其他的办法实现过了。本实例包括三个工程:EquipmentApply(设备申请exe)、EquipmentApprove(设备审批exe)、EquipmentApplyWorkflowLib(申请审批流程库dll)。首先新建Windows应用程序项目EquipmentApply,界面如图所示:
<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,界面如图所示:
<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,建立流程图:
<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>
该流程包括三个外部方法Activities(CreateApply、ApproveApply、EscalateApply)和两个外部事件Activities(EquipmentApprove、ApplyEscalated),一个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);