1. 程式人生 > >起飛 踏上.NET Framework 3.5開發之旅

起飛 踏上.NET Framework 3.5開發之旅

這個例子在我們的專案中已經實際應用,所以我想叫做例項應該沒什麼問題。這是一個經典的裝置申請審批流程,大家很多時候已經用其他的辦法實現過了。本例項包括三個工程:EquipmentApply(裝置申請exe)、EquipmentApprove(裝置審批exe)、EquipmentApplyWorkflowLib(申請審批流程庫dll)。首先新建Windows應用程式專案EquipmentApply,介面如圖所示:

新增Windows應用程式專案EquipmentApprove,介面如圖所示:

新增Workflow中的Sequential Workflow Library專案EquipmentApplyWorkflowLib

,建立流程圖:

該流程包括三個外部方法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 Persistenceservice

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);