.net之工作流工程展示及代码分享(四)主控制类
现在应该讲主控制类了,为了不把系统弄得太复杂,所以就用一个类作为主要控制类(服务类),作为前端、后端、业务逻辑的控制类。
WorkflowService类的类图如下:
该类的构造函数:
public WorkflowService(IWorkflowDB workflowDb, IWorkflowMethods workflowMethods)
{
_iWorkflowDb = workflowDb;
_iWorkflowMethods = workflowMethods;
}
通过简单工厂方法返回类的实例:
/// <summary>
/// 程序主调用方法
/// </summary>
/// <returns></returns>
public static WorkflowService GetWorkflowService()
{
IWorkflowDB iWorkflowDb;
try
{
string dbSavingProvider = WorkFlowUtility.GetConfiguration("DataBaseProvider").ToLower();
switch (dbSavingProvider)
{
case "oracle":
iWorkflowDb = new OracleWorkFlowDBUtility();
break;
case "sqlserver":
//iWorkflowDb = new SqlServerWorkFlowDBUtility();
//break;
default:
iWorkflowDb = (IWorkflowDB) Assembly.Load(dbSavingProvider).CreateInstance(dbSavingProvider);
break;
} }
catch (Exception)
{
throw new WorkFlowConfigurationNotImplementException("数据库配置失败!");
} IWorkflowMethods iWorkflowMethods;
try
{
string dbInterface = WorkFlowUtility.GetConfiguration("WorkflowConfigurationNameSpace");
iWorkflowMethods = (IWorkflowMethods)Assembly.Load(dbInterface).CreateInstance(dbInterface + ".WorkflowConfiguration");
}
catch (Exception ex)
{
throw new WorkFlowConfigurationNotImplementException("应用程序实例配置失败!");
} return new WorkflowService(iWorkflowDb, iWorkflowMethods);
}
所有方法返回的类型都是WorkflowServiceResponse类型,该类定义如下:
public class WorkflowServiceResponse
{
public WorkflowServiceResponse()
{
Success = false;
}
public bool Success { get; set; }
public string Message { get; set; }
public dynamic ReturnEntity { get; set; }
}
使用了Request-Response模式,其中返回的实体使用了.net4.0新增的Dynamic类型,这样就不用做抽象类,然后各种不同的返回类型来继承基类了。
调用的方法如下:
var wfs = WorkflowService.GetWorkflowService();
var wfsr = wfs.GetFlowById(flowId);
if (!wfsr.Success)
{
this.ShowAndRedirects("参数错误", "FlowManager.aspx");
return;
}
var flow = wfsr.ReturnEntity as Flow;
.......
那GetFlowById是怎么写的呢?
/// <summary>
/// 根据流程Id得到一个流程的情况
/// </summary>
/// <param name="flowId"></param>
/// <returns></returns>
public WorkflowServiceResponse GetFlowById(Guid flowId)
{
var wfsr = new WorkflowServiceResponse();
try
{
var flow = _iWorkflowDb.GetFlows().SingleOrDefault(f => f.FlowId == flowId);
if (flow != null)
{
wfsr.ReturnEntity = flow;
wfsr.Success = true;
}
}
catch (Exception ex)
{
wfsr.Message = ex.ToString();
}
return wfsr;
}
这样前后端都串起来了。
在IWorkflowDB接口定义里,GetFlows返回的是List<Flow>对象,所以这么做数据接口存在一定的性能问题,如果改成IQueryable<Flow>就能够返回Linq表达式,实现Lazy-Loaing的模式,但是Oracle不支持Linq查询,以后换EF看看......
大家注意到了WorkflowService类里面还有个IWorkflowMethods接口。对了,这个接口就是和其它系统交互的关键,定义如下:
public interface IWorkflowMethods
{
Person GetCurrentLoginPerson();
IList<Person> GetPersonByCondition(SearchCriteria searchCriteria);
bool SendMail(Person person, string message);
bool SendMessage(Person person, string message);
string GetAutoCompleteValueByType(string autoCompleteType);
IList<string> GetUserRoleGroupNames(Person person);
}
这些方法分别是获取当前登录用户、根据条件获取应该审核流程的用户、调用原系统方法法邮件、发短信,用于表单处理中的自动填入用户姓名、职务等,获取用户所在的组(有些流程只有特定组可以申请)。
在其中一个系统中的实现方法如下:
public IList<Person> GetPersonByCondition(SearchCriteria searchCriteria)
{
var flowLaunchPerson = searchCriteria.FlowLaunchPerson;
string sql = string.Empty;
IList<Person> persons = new List<Person>();
switch (searchCriteria.NextPersonWorkGroupName)
{
case ".....":
break;
case "xxx审核":
{
sql = string.Format(" jsgh in (select gh from VM_TUAN....ERGR where zbid in" +
" (select zbid from TUA....ELATIONSHIP where gh = '{0}' or xh = '{0}')" +
" and lv = 4 and zwname = '辅导员)') ", flowLaunchPerson.PersonId);
break;
}
case ".....审核":
{
sql = string.Format(" jsgh in (select gh from VM.....HERGR where zbid in" +
" (select zbid from TUA....IONSHIP where gh = '{0}' or xh = '{0}')" +
" and lv = 4 and zwname = '...') ", flowLaunchPerson.PersonId);
break;
};
case ".....审核":
........
break;
default:
break;
} var teachers = new B.....GetModelList(sql); if (teachers.Count > )
{
foreach (var teacher in teachers)
{
Person person = new Person()
{
PersonId = teacher.....,
PersonName = teacher.J....,
PersonEmail = teacher.E....,
};
persons.Add(person);
}
}
else
{
throw new WorkFlowAuditPersonNotFoundException("没有找到审核对象!");
}
return persons;
}
最后分享服务类中两个核心的方法
新建流程:
/// <summary>
/// 根据流程Id建立新的流程
/// </summary>
/// <param name="workflowAddStepParameter"></param>
/// <returns></returns>
public WorkflowServiceResponse CreateNewFlowInstance(WorkflowAddStepParameter workflowAddStepParameter)
{
var wfsr = new WorkflowServiceResponse();
string message = string.Empty; if (workflowAddStepParameter.Flow == null)
{
wfsr.Message = "参数错误!";
}
else
{
var person = GetCurrentLoginPerson(); var flowInstance = new FlowInstance();
flowInstance.FlowInstantId = Guid.NewGuid();
flowInstance.Flow = workflowAddStepParameter.Flow;
flowInstance.Creator = person;
flowInstance.CreateDate = DateTime.Now; var flowInstanceStep = new FlowInstanceStep();
flowInstanceStep.StepInstanceId = Guid.NewGuid();
flowInstanceStep.PersonSignatures = new List<WorkflowPersonSignature>()
{
new WorkflowPersonSignature()
{
Person = person,
SignatureDate = DateTime.Now,
SignatureStatus = WorkflowConstant.SignatureStatus.Start,
}
};
flowInstanceStep.FlowStep = workflowAddStepParameter.Flow.FlowSteps.Single(s => s.IsStartStep); flowInstanceStep.WriteValues = workflowAddStepParameter.WritedValues;
flowInstanceStep.CreateDate = DateTime.Now;
flowInstanceStep.ProcessDate = DateTime.Now;
flowInstanceStep.FileList = workflowAddStepParameter.AttachFiles; var flowInstanceStep2 = new FlowInstanceStep();
flowInstanceStep2.CreateDate = DateTime.Now;
flowInstanceStep2.FlowStep =
workflowAddStepParameter.Flow.FlowSteps.Single(
f => f.PreviousStepId == workflowAddStepParameter.Flow.FlowSteps.Single(p => p.IsStartStep).StepId);
flowInstanceStep2.StepInstanceId = Guid.NewGuid();
flowInstanceStep2.StepStatus = WorkflowConstant.SignatureStatus.Undeal; var flowProcessPersons =
_iWorkflowMethods.GetPersonByCondition(new SearchCriteria()
{
CurrentLoginPerson = person,
FlowLaunchPerson = person,
NextPersonWorkGroupName = flowInstanceStep2.FlowStep.RightGroupTitle,
}); var personSignatures = new List<WorkflowPersonSignature>(); if (flowProcessPersons.Count == )
{
throw new WorkFlowAuditPersonNotFoundException();
}
foreach (var flowProcessPerson in flowProcessPersons)
{
personSignatures.Add(
new WorkflowPersonSignature()
{
Person = flowProcessPerson,
SignatureStatus = WorkflowConstant.SignatureStatus.Undeal,
});
SendMessages(person, flowProcessPerson, WorkflowConstant.SignatureStatus.Undeal);
}
flowInstanceStep2.PersonSignatures = personSignatures;
flowInstance.FlowStepInstances = new List<FlowInstanceStep>()
{
flowInstanceStep,
flowInstanceStep2
}; try
{
wfsr.Success = _iWorkflowDb.SaveFlowInstance(flowInstance);
wfsr.ReturnEntity = flowInstance;
}
catch (Exception ex)
{
wfsr.Message = ex.ToString();
}
}
return wfsr;
}
增加流程步骤:
public WorkflowServiceResponse AddFlowInstanceStep(WorkflowAddStepParameter workflowAddStepParameter)
{
var wfsr = new WorkflowServiceResponse();
var flowInstance = workflowAddStepParameter.CurrentInstance; if (flowInstance != null)
{
try
{
var person = GetCurrentLoginPerson();
var currentStepIndex = flowInstance.FlowStepInstances.Count - ;
//idempotent check
var flowInstanceInDb = GetFlowInstanceByInstanceId(flowInstance.FlowInstantId).ReturnEntity as FlowInstance;
if (flowInstanceInDb.FlowStepInstances.Count != flowInstance.FlowStepInstances.Count)
{
wfsr.Message = "您已经处理过该流程,请不要重复提交(或者该流程已经由其他老师处理完成)";
return wfsr;
} var currentPersonSignatures = flowInstance.FlowStepInstances[currentStepIndex].PersonSignatures;
//idempotent check
bool deal = false;
for (int i = ; i < currentPersonSignatures.Count; i++)
{
if (currentPersonSignatures[i].Person.PersonId == person.PersonId)
{
if (currentPersonSignatures[i].SignatureStatus != WorkflowConstant.SignatureStatus.Undeal)
{
wfsr.Message = "该流程已经处理过";
return wfsr;
}
flowInstance.FlowStepInstances[currentStepIndex].PersonSignatures[i].SignatureDate =
DateTime.Now;
flowInstance.FlowStepInstances[currentStepIndex].PersonSignatures[i].SignatureStatus =
workflowAddStepParameter.SignatureStatus;
flowInstance.FlowStepInstances[currentStepIndex].PersonSignatures[i].Memo = workflowAddStepParameter.Memo;
deal = true;
}
}
if (!deal)
{
wfsr.Message = "您已经处理过该流程,请不要重复提交(或者该流程已经由其他老师处理完成)";
return wfsr;
} flowInstance.FlowStepInstances[currentStepIndex].WriteValues = workflowAddStepParameter.WritedValues;
flowInstance.FlowStepInstances[currentStepIndex].ProcessDate = DateTime.Now; switch (workflowAddStepParameter.SignatureStatus)
{
case WorkflowConstant.SignatureStatus.Passed:
{
if (flowInstance.FlowStepInstances[currentStepIndex].FlowStep.CounterSignatureMode ==
WorkflowConstant.CounterSignatureMode.OneApprove)
{
flowInstance.FlowStepInstances[currentStepIndex].StepStatus =
WorkflowConstant.SignatureStatus.Passed;
}
else if (flowInstance.FlowStepInstances[currentStepIndex].FlowStep.CounterSignatureMode ==
WorkflowConstant.CounterSignatureMode.AllApprove)
{
if (
flowInstance.FlowStepInstances[currentStepIndex].PersonSignatures.All(
s => s.SignatureStatus == WorkflowConstant.SignatureStatus.Passed))
{
flowInstance.FlowStepInstances[currentStepIndex].StepStatus =
WorkflowConstant.SignatureStatus.Passed;
}
else
{
flowInstance.FlowStepInstances[currentStepIndex].StepStatus =
WorkflowConstant.SignatureStatus.PartialPassed;
}
}
if (flowInstance.FlowStepInstances[currentStepIndex].StepStatus ==
WorkflowConstant.SignatureStatus.Passed)
{
if (flowInstance.FlowStepInstances[currentStepIndex].FlowStep.IsLastStep)
{
flowInstance.FlowStatus = WorkflowConstant.SignatureStatus.Finish;
var lastStep = new FlowInstanceStep();
lastStep.StepInstanceId = Guid.NewGuid();
lastStep.CreateDate = DateTime.Now;
lastStep.FlowStep = new FlowStep()
{
StepName = "流程结束",
};
lastStep.ProcessDate = DateTime.Now;
lastStep.StepStatus = WorkflowConstant.SignatureStatus.Finish;
flowInstance.FlowStepInstances.Add(lastStep);
}
else
{
var nextStep = new FlowInstanceStep();
nextStep.StepInstanceId = Guid.NewGuid();
nextStep.CreateDate = DateTime.Now;
nextStep.FlowStep =
flowInstance.Flow.FlowSteps.Single(
f =>
f.PreviousStepId ==
flowInstance.FlowStepInstances[currentStepIndex].FlowStep.StepId);
nextStep.StepStatus = WorkflowConstant.SignatureStatus.Undeal; var flowProcessPersons =
_iWorkflowMethods.GetPersonByCondition(new SearchCriteria()
{
CurrentLoginPerson = _iWorkflowMethods.GetCurrentLoginPerson(),
FlowLaunchPerson = flowInstance.Creator,
NextPersonWorkGroupName = nextStep.FlowStep.RightGroupTitle,
}); var personSignatures = new List<WorkflowPersonSignature>(); if (flowProcessPersons.Count == )
{
throw new WorkFlowAuditPersonNotFoundException();
}
foreach (var flowProcessPerson in flowProcessPersons)
{
personSignatures.Add(
new WorkflowPersonSignature()
{
Person = flowProcessPerson,
SignatureStatus = WorkflowConstant.SignatureStatus.Undeal,
});
}
nextStep.PersonSignatures = personSignatures;
flowInstance.FlowStepInstances.Add(nextStep);
}
} break;
}
case WorkflowConstant.SignatureStatus.Stopped:
flowInstance.FlowStepInstances[currentStepIndex].StepStatus =
WorkflowConstant.SignatureStatus.Stopped;
flowInstance.FlowStatus = WorkflowConstant.SignatureStatus.Stopped; break;
case WorkflowConstant.SignatureStatus.RejectToFirstStep:
{
flowInstance.FlowStepInstances[currentStepIndex].StepStatus =
WorkflowConstant.SignatureStatus.RejectToFirstStep;
var nextStep = new FlowInstanceStep();
nextStep.StepInstanceId = Guid.NewGuid();
nextStep.CreateDate = DateTime.Now;
nextStep.FlowStep =
flowInstance.Flow.FlowSteps.Single(
f => f.IsStartStep);
nextStep.StepStatus = WorkflowConstant.SignatureStatus.Undeal; var personSignatures = new List<WorkflowPersonSignature>();
personSignatures.Add(new WorkflowPersonSignature()
{
Person =
flowInstance.FlowStepInstances.Single(f => f.FlowStep.IsStartStep)
.PersonSignatures[].Person,
SignatureStatus = WorkflowConstant.SignatureStatus.Undeal
}); nextStep.PersonSignatures = personSignatures;
flowInstance.FlowStepInstances.Add(nextStep); break;
}
case WorkflowConstant.SignatureStatus.RejectToPreviousStep:
{
flowInstance.FlowStepInstances[currentStepIndex].StepStatus =
WorkflowConstant.SignatureStatus.RejectToPreviousStep; var nextStep = new FlowInstanceStep();
nextStep.StepInstanceId = Guid.NewGuid();
nextStep.CreateDate = DateTime.Now;
nextStep.FlowStep =
flowInstance.Flow.FlowSteps.Single(
f =>
f.StepId ==
flowInstance.FlowStepInstances[currentStepIndex].FlowStep.PreviousStepId);
nextStep.StepStatus = WorkflowConstant.SignatureStatus.Undeal; var flowProcessPersons =
_iWorkflowMethods.GetPersonByCondition(new SearchCriteria()
{
CurrentLoginPerson = _iWorkflowMethods.GetCurrentLoginPerson(),
FlowLaunchPerson = flowInstance.Creator,
NextPersonWorkGroupName = nextStep.FlowStep.RightGroupTitle,
}); var personSignatures = new List<WorkflowPersonSignature>(); if (flowProcessPersons.Count == )
{
throw new WorkFlowAuditPersonNotFoundException();
}
foreach (var flowProcessPerson in flowProcessPersons)
{
personSignatures.Add(
new WorkflowPersonSignature()
{
Person = flowProcessPerson,
SignatureStatus = WorkflowConstant.SignatureStatus.Undeal,
});
}
nextStep.PersonSignatures = personSignatures;
flowInstance.FlowStepInstances.Add(nextStep); break;
}
default:
break; } flowInstance.LastDealDate = DateTime.Now; wfsr.Success = _iWorkflowDb.SaveFlowInstance(flowInstance);
wfsr.ReturnEntity = flowInstance;
}
catch (Exception ex)
{
wfsr.Message = ex.ToString();
}
}
return wfsr; }
感觉用DDD的思想写程序还是蛮舒服的。(感谢Steven的指出,操纵流程类并没体现DDD思想。在操纵Form类里面的有的,代码没贴出)
下回讲一下前端。
谢谢大家!
本系列导航:
- .net之工作流工程展示及代码分享(预告)
- .net之工作流工程展示及代码分享(一)工作流表单
- .net之工作流工程展示及代码分享(二)工作流引擎
- .net之工作流工程展示及代码分享(三)数据存储引擎
- .net之工作流工程展示及代码分享(四)主控制类
- .net之工作流工程展示及代码分享(五)前端交互
.net之工作流工程展示及代码分享(四)主控制类的更多相关文章
- .net之工作流工程展示及代码分享(三)数据存储引擎
数据存储引擎是本项目里比较有特色的模块. 特色一,使用接口来对应不同的数据库.数据库可以是Oracle.Sqlserver.MogoDB.甚至是XML文件.采用接口进行对应: public inter ...
- .net之工作流工程展示及代码分享(二)工作流引擎
在介绍完表单类的时候,接下来介绍工作流引擎,主要由四个类组成,分别是流程.流程步骤.流程实例.流程步骤实例类. 流程类: [Serializable] public class Flow { [Xml ...
- .net之工作流工程展示及代码分享(一)工作流表单
Workflow表单的作用是能够在客户端进行表单设计,然后在流程中动态开放哪些输入框可以供用户填写. 在这里我扩展了一个常用的WebEditor工具——KindEditor,能够插入自定义的html符 ...
- .net之工作流工程展示及代码分享(预告)
最近在帮公司做一个工作流程序模块,要求是可以嵌入到各种现有的程序中去.我想把自己制作的思路和过程同大家分享. 先上一张结构图: 由于该项目我一个人做,所以系统结构不能太复杂. 用到的技术主要有:DDD ...
- net之工作流工程展示及代码分享(记录)
http://www.cnblogs.com/thanks/p/4183235.html
- JAVA基础代码分享--DVD管理
问题描述 为某音像店开发一个迷你DVD管理器,最多可存6张DVD,实现碟片的管理. 管理器具备的功能主要有: 1.查看DVD信息. 菜单选择查看功能,展示DVD的信息. 2.新增DVD信息 选择新增功 ...
- 一款WP小游戏代码分享
首先声明游戏是H5的代码,当然游戏部分不是我写的,感谢@LeZhi的分享,关于H5我还在学习,这里只是简单介绍一下如何把一款现成的H5游戏封装成一款WP游戏(当然也可以做成Windows游戏). 大家 ...
- Unity多媒体展示项目经验分享-ImageEffect+动态绑定
Unity多媒体展示项目经验分享-ImageEffect+动态绑定+网络通信 <ignore_js_op> “海尔科技展墙”是去年年初我们为上海家电博览会制作的一个多媒体展项,有限的工期以 ...
- Java生鲜电商平台-生鲜售后系统的退款架构设计与代码分享
Java生鲜电商平台-生鲜售后系统的退款架构设计与代码分享 说明:任何一个电商行业都涉及到退货与退款的问题,但是生鲜电商行业还设有一个显著的特点,那就是换货.在人性面前,各种各样的退货,退款,换货的售 ...
随机推荐
- ZeroMQ接口函数之 :zmq_setsockopt –设置ZMQ socket的属性
ZeroMQ API 目录 :http://www.cnblogs.com/fengbohello/p/4230135.html 本文地址 :http://www.cnblogs.com/fengbo ...
- 使用JQuery UI selectmenu, onchange事件失效
今天, 在用jQuery UI的一套东西是发现<select class="dropmenu" onchange="do();"></sele ...
- Winform TextBox中只能输入数字的几种常用方法(C#)
方法一: private void tBox_KeyPress(object sender, KeyPressEventArgs e) { ; //禁止空格键 )) return; //处理负数 if ...
- vs 调试的时候 使用IP地址,局域网的设备可以访问并调试
由于项目中主要是用于微信端的访问,所以使用PC来调试就很麻烦,那么就想到用IP地址来调试,那么就手机或者移动端就可以访问,并且进行调试了 那么,主要的设置如下几步: 1. 首先保证你的项目的属性的服务 ...
- QT的程序开机自启动方法
/home/fa/.config/lxsession/LXDE/autostart文件最后添加脚本
- javascript:算法之for循环
一.for中的表达式 ①短路表达式 a && b是表达式:当执行的时候如果表达式a结果不是0,就会执行表达式b.如果表达式a执行的结果是0,表达式b不执行 ②i++与++i的不同 ++ ...
- Hardware Solutions CACHE COHERENCE AND THE MESI PROTOCOL
COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION Hardware-based soluti ...
- sql server 游标 写给自己
) --定义两个局部变量 @id @name 全局变量是两个@@name ) Declare Cur Cursor For --定义一个游标 select id,name from temp1 --查 ...
- TID大会学习心得之敏捷软件架构-微服务
敏捷微服务构建 王威: TW咨询师.架构转型教练.敏捷技术教练 敏捷的目标 敏捷的目标是提升效率?降低成本?减员增效? 敏捷:关注价值.快速反馈.快速响应.其的目标是提升响应力,响应力的提升不一定会提 ...
- RelativeLayout中的格局,自适应宽度布局
RelativeLayout中的布局,自适应宽度布局 该图片中为android布局:总布局为 RelativeLayoutAtLeft 为居左 <TextView android:backgro ...