隐藏

C#最简单的工作流 (转)

发布:2016/1/6 21:49:00作者:管理员 来源:本站 浏览次数:1179

最近一直在做一个小项目,这个项目是高等学校岗位聘用审核系统,该系统涉及到多个部门审批,同时还要求管理员能对审核部门进行管理,编辑、添加和删除等。在了解到这些系统需要后,我首先想到利用微软sharepoint2007来开发,毕竟微软的工作流引擎已经非常成熟了,而且让人有种站在巨人肩膀的感觉(HoHo)。经过一段时间对sharepoint2007的学习,这套系统实在是太大了,而早几个月前这套系统在国内几乎没有一本成形的开发书籍,只有系统管理类书籍,常因为一个问题而耽误好几天,整个开发就这样停滞了,后来仔细想想其实我所开发的系统需要的工作流只是最简单工作流应用,因此也就有了自己设计一个小型工作流的想法,成就了本文,希望对大家有帮助。
我设计的这个小型工作流只具有“运行先后”这个概念,没有其它判断条件,前一批工作流活动完成,后一批工作流活动开始。因为工作流类(Workflow)的结构非常简单:
class Workflow()
{
private int _id; //工作流活动ID
private string _name; //工作流活动名称
private string _url; //工作流活动相应的网页
private int _seq; //运行顺序
private int _statusBit; //状态位
}

工作流活动ID不用解释了,工作流活动名称可是任何字符,这样是为了更好区分工作流活动。url的设计是由INFOPATH联想到的,微软sharepoint2007可以通过为每个工作流活动指定相应的编辑表单,可以是网页也可以infopath设计的表单,这样的好处是让工作流的不同活动具有不同的用户界面,sharepoint2007可以在feature.xml里设置,而我这就使用url字段记录一个网页链接,不同工作流活动对应不同的网页。seq是每个工作流运行的顺序,从零开始,依次为0、1、2、3......,这个字段正是为了设置工作流的运行顺序,并行的工作流活动可以设置成相同的运行顺序。可能有人会问怎么标识工作流活动已经完成呢,这个标识正是由statusBit状态位来实现的,每个申请表中都含有一个status字段,这个字段默认为50个‘0’组成的字符串,status字段是为了记录当前申请表哪些工作流活动完成了,1为完成0为未完成,statusBit状态位正是将工作流活动与申请表中的状态联系起来,也许有些朋友会认为让系统自动分配好更好,第一个工作流活动联系第一位状态,第二个工作流活动联系第二位状态,等等。我这么做的好处是考虑到可能会有多个工作流活动只需完成其中一个活动就情况,就像逻辑判断中的“或”一样,在这种情况我们只需将多个工作流活动状态位设置成一样就可以达到目的了。

光说而没有实例可能有些朋友不太明白,下面我以项目中工作流流程为例:
本系统的流程是这样的(不好意思,linux下画的图效果没visio好):
C最简单的工作流 (转) - 叶秋 - walden的博客
由流程图得出各工作流实例如下:
ID NAME URL SEQ STATUSBIT
1 申请人提交申请表 user_main.aspx 0 1
2 各部门审查 depart_check.aspx 1 2
3 科技处审查 check_main.aspx 2 3
4 教务处审查 check_main.aspx 2 4
5 研究生院审查 check_main.aspx 2 5
6 人事科审查 check_main.aspx 2 6
7 人事处审查 recheck.aspx 3 7
8 专家评议 expert_main.aspx 4 8
9 完成聘用 null 5 9

想必由以上实例应该很容易看出流程图了,看到这应该明白了吧

下面是我的工作流类的c#实现:


using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Collections.Generic;

///< summary>
/// 工作流类
///< /summary>
public class Workflow
{
private int _id;
///< summary>
/// 工作流编号
///< /summary>
public int Id
{
get { return _id; }
set { _id = value; }
}


private string _name;
///< summary>
/// 工作流名字
///< /summary>
public string Name
{
get { return _name; }
set { _name = value; }
}

private string _url;
///< summary>
/// 工作流使用网页
///< /summary>
public string Url
{
get { return _url; }
set { _url = value; }
}

private int _seq;
///< summary>
/// 工作流运行序号
///< /summary>
public int Seq
{
get { return _seq; }
set { _seq = value; }
}

private int _statusBit;
///< summary>
/// 状态位
///< /summary>
public int StatusBit
{
get { return _statusBit; }
set { _statusBit = value; }
}

public Workflow()
{
}

public Workflow(int id, string name, string url, int seq, int statusBit)
{
this.Id = id;
this.Name = name;
this.Url = url;
this.Seq = seq;
this.StatusBit = statusBit;
}

public Workflow(SqlDataReader dr)
{
this.Id = Convert.ToInt32(dr["id"]);
this.Name = dr["name"].ToString();
this.Url = dr["url"].ToString();
this.Seq = Convert.ToInt32(dr["seq"]);
this.StatusBit = Convert.ToInt32(dr["statusBit"]);
}

public int Add()
{
string procName = "pr_AddWorkflow";
SqlParameter[] prams = { new SqlParameter("@name",SqlDbType.NVarChar,50),
new SqlParameter("@url",SqlDbType.NVarChar,500),
new SqlParameter("@seq",SqlDbType.Int),
new SqlParameter("@statusbit",SqlDbType.Int)};
prams[0].Value = Name;
prams[1].Value = Url;
prams[2].Value = Seq;
prams[3].Value = StatusBit;
return Database.runExecute(procName, prams);
}

public int Delete()
{
string procName = "pr_DeleteWorkflow";
SqlParameter[] prams = { new SqlParameter("@id",SqlDbType.BigInt)};
prams[0].Value = Id;
return Database.runExecute(procName, prams);
}

public int Update()
{
string procName = "pr_UpdateWorkflow";
SqlParameter[] prams = { new SqlParameter("@id",SqlDbType.BigInt),
new SqlParameter("@name",SqlDbType.NVarChar,50),
new SqlParameter("@url",SqlDbType.NVarChar,500),
new SqlParameter("@seq",SqlDbType.Int),
new SqlParameter("@statusbit",SqlDbType.Int)};
prams[0].Value = Id;
prams[1].Value = Name;
prams[2].Value = Url;
prams[3].Value = Seq;
prams[4].Value = StatusBit;
return Database.runExecute(procName, prams);
}

///< summary>
/// 根据工作流编号获得工作流信息
///< /summary>
/// <param name="id">工作流编号</param>
///< returns>工作流信息</returns>
public static Workflow GetWorkflowById(int id)
{
Workflow wl = new Workflow();
string procName = "pr_GetWorkflowById";
SqlParameter[] prams = { new SqlParameter("@Id",SqlDbType.BigInt)};
prams[0].Value = id;
SqlDataReader dr = Database.runProcGetReader(procName, prams);
while (dr.Read())
{
wl = new Workflow(dr);
}
dr.Close();
return wl;
}

///< summary>
/// 根据工作流编号获得工作流网页地址
///< /summary>
/// <param RealName="workflowId">工作流编号</param>
///< returns>工作流网页地址</returns>
public static string GetWorkflowUrlById(int workflowId)
{
string procName = "pr_GetWorkflowUrlById";
SqlParameter[] prams = { new SqlParameter("@workflowId",SqlDbType.BigInt),
new SqlParameter("@url",SqlDbType.NVarChar,500)};
prams[0].Value = workflowId;
prams[1].Direction = ParameterDirection.Output;
Database.runExecute(procName, prams);
return prams[1].Value.ToString();
}

///< summary>
/// 返回工作流个数
///< /summary>
///< returns>工作流个数</returns>
public static int GetWorkflowNum()
{
string procName = "pr_GetWorkflowNum";
SqlParameter[] prams = { new SqlParameter("@num",SqlDbType.Int)};
prams[0].Direction = ParameterDirection.Output;
Database.runExecute(procName,prams);
return Convert.ToInt32(prams[0].Value);
}

///< summary>
/// 设置申请表的工作流完成状态
///< /summary>
/// <param name="reportId">申请表编号</param>
/// <param name="workflowId">工作流编号</param>
/// <param name="status">完成状态</param>
///< returns></returns>
public static int SetActivityStatus(int reportId, int workflowId, bool status)
{
string procName = "pr_SetActivityStatus";
SqlParameter[] prams = { new SqlParameter("@reportId",SqlDbType.BigInt),
new SqlParameter("@workflowId",SqlDbType.BigInt),
new SqlParameter("@status",SqlDbType.Bit)};
prams[0].Value = reportId;
prams[1].Value = workflowId;
prams[2].Value = status;
return Database.runExecute(procName, prams);
}

///< summary>
/// 获得申请表的工作流完成状态
///< /summary>
/// <param name="reportId">申请表编号</param>
/// <param name="workflowId">工作流编号</param>
///< returns>完成状态</returns>
public static bool GetActivityStatus(int reportId, int workflowId)
{
string procName = "pr_GetActivityStatus";
SqlParameter[] prams = { new SqlParameter("@reportId",SqlDbType.BigInt),
new SqlParameter("@workflowId",SqlDbType.BigInt),
new SqlParameter("@status",SqlDbType.Bit)};
prams[0].Value = reportId;
prams[1].Value = workflowId;
prams[2].Direction = ParameterDirection.Output;
Database.runExecute(procName, prams);
return Convert.ToBoolean(prams[2].Value);
}

///< summary>
/// 获得工作流中当前活动的下一批运行活动
///< /summary>
/// <param name="workflowId">当前活动编号</param>
///< returns>下一批运行活动</returns>
public static List<Workflow> GetNextWorkflow(int workflowId)
{
List<Workflow> workflows = new List<Workflow>();
string procName = "pr_GetNextWorkflow";
SqlParameter[] prams = { new SqlParameter("@workflowId",SqlDbType.BigInt)};
prams[0].Value = workflowId;
SqlDataReader dr = Database.runProcGetReader(procName, prams);
while (dr.Read())
{
Workflow wf = new Workflow(dr);
workflows.Add(wf);
}
return workflows;
}

///< summary>
/// 获得工作流中当前活动的上一批运行活动
///< /summary>
/// <param name="workflowId">当前活动编号</param>
///< returns>上一批运行活动</returns>
public static List<Workflow> GetPreviousWorkflow(int workflowId)
{
List<Workflow> workflows = new List<Workflow>();
string procName = "pr_GetPreviousWorkflow";
SqlParameter[] prams = { new SqlParameter("@workflowId",SqlDbType.BigInt)};
prams[0].Value = workflowId;
SqlDataReader dr = Database.runProcGetReader(procName, prams);
while (dr.Read())
{
Workflow wf = new Workflow(dr);
workflows.Add(wf);
}
return workflows;
}

///< summary>
/// 判断申请表进行的上一批工作流是否完成
///< /summary>
/// <param name="workflowId"></param>
/// <param name="reportId"></param>
///< returns></returns>
public static bool IsPreviousWorkflowFinished(int workflowId, int reportId)
{
bool flag = true;
List<Workflow> workflows = new List<Workflow>();
workflows = GetPreviousWorkflow(workflowId);
foreach (Workflow wf in workflows)
{
string status = Reports.GetCurrentStatusById(reportId);
if (status.Substring(wf.StatusBit - 1, 1) == "0")
{
flag = false;
break;
}
}
return flag;
}

///< summary>
/// 判断申请表进行的下一批工作流是否开始
///< /summary>
/// <param name="workflowId"></param>
/// <param name="reportId"></param>
///< returns></returns>
public static bool IsNextWorkflowStarted(int workflowId, int reportId)
{
bool flag = false;
List<Workflow> workflows = new List<Workflow>();
workflows = GetNextWorkflow(workflowId);
foreach (Workflow wf in workflows)
{
string status = Reports.GetCurrentStatusById(reportId);
if (status.Substring(wf.StatusBit - 1, 1) == "1")
{
flag = true;
break;
}
}
return flag;
}

///< summary>
/// 获得工作流中第一个活动
///< /summary>
///< returns>第一个活动</returns>
public static Workflow GetFirstActivity()
{
Workflow wf = new Workflow();
string procName = "pr_GetFirstActivity";
SqlDataReader dr = Database.runProcGetReader(procName);
while (dr.Read())
{
wf = new Workflow(dr);
}
return wf;
}

///< summary>
/// 获得工作流中最后一个活动
///< /summary>
///< returns>最后一个活动</returns>
public static Workflow GetLastActivity()
{
Workflow wf = new Workflow();
string procName = "pr_GetLastActivity";
SqlDataReader dr = Database.runProcGetReader(procName);
while (dr.Read())
{
wf = new Workflow(dr);
}
return wf;
}

///< summary>
/// 获得所有工作流活动
///< /summary>

public static List<Workflow> GetAllWorkflow()
{
List<Workflow> workflows = new List<Workflow>();
string procName = "pr_GetAllWorkflows";
SqlDataReader dr = Database.runProcGetReader(procName);
while (dr.Read())
{
workflows.Add(new Workflow(dr));
}
return workflows;
}
}

///< summary>
/// 按运行顺序排序接口
///< /summary>

public class ISortWorkflows : IComparer<Workflow>
{
public int Compare(Workflow x, Workflow y)
{
if (x.Seq < y.Seq) return -1;
else if (x.Seq > y.Seq) return 1;
else return 0;
}
}