.net之工作流工程展示及代码分享(四)主控制类
现在应该讲主控制类了,为了不把系统弄得太复杂,所以就用一个类作为主要控制类(服务类),作为前端、后端、业务逻辑的控制类。
WorkflowService类的类图如下:
该类的构造函数:
1 public WorkflowService(IWorkflowDB workflowDb, IWorkflowMethods workflowMethods) 2 { 3 _iWorkflowDb = workflowDb; 4 _iWorkflowMethods = workflowMethods; 5 }
通过简单工厂方法返回类的实例:
1 /// <summary> 2 /// 程序主调用方法 3 /// </summary> 4 /// <returns></returns> 5 public static WorkflowService GetWorkflowService() 6 { 7 IWorkflowDB iWorkflowDb; 8 try 9 { 10 string dbSavingProvider = WorkFlowUtility.GetConfiguration("DataBaseProvider").ToLower(); 11 switch (dbSavingProvider) 12 { 13 case "oracle": 14 iWorkflowDb = new OracleWorkFlowDBUtility(); 15 break; 16 case "sqlserver": 17 //iWorkflowDb = new SqlServerWorkFlowDBUtility(); 18 //break; 19 default: 20 iWorkflowDb = (IWorkflowDB) Assembly.Load(dbSavingProvider).CreateInstance(dbSavingProvider); 21 break; 22 } 23 24 } 25 catch (Exception) 26 { 27 throw new WorkFlowConfigurationNotImplementException("数据库配置失败!"); 28 } 29 30 IWorkflowMethods iWorkflowMethods; 31 try 32 { 33 string dbInterface = WorkFlowUtility.GetConfiguration("WorkflowConfigurationNameSpace"); 34 iWorkflowMethods = (IWorkflowMethods)Assembly.Load(dbInterface).CreateInstance(dbInterface + ".WorkflowConfiguration"); 35 } 36 catch (Exception ex) 37 { 38 throw new WorkFlowConfigurationNotImplementException("应用程序实例配置失败!"); 39 } 40 41 return new WorkflowService(iWorkflowDb, iWorkflowMethods); 42 }
所有方法返回的类型都是WorkflowServiceResponse类型,该类定义如下:
1 public class WorkflowServiceResponse 2 { 3 public WorkflowServiceResponse() 4 { 5 Success = false; 6 } 7 public bool Success { get; set; } 8 public string Message { get; set; } 9 public dynamic ReturnEntity { get; set; } 10 }
使用了Request-Response模式,其中返回的实体使用了.net4.0新增的Dynamic类型,这样就不用做抽象类,然后各种不同的返回类型来继承基类了。
调用的方法如下:
1 var wfs = WorkflowService.GetWorkflowService(); 2 var wfsr = wfs.GetFlowById(flowId); 3 if (!wfsr.Success) 4 { 5 this.ShowAndRedirects("参数错误", "FlowManager.aspx"); 6 return; 7 } 8 var flow = wfsr.ReturnEntity as Flow; 9 .......
那GetFlowById是怎么写的呢?
1 /// <summary> 2 /// 根据流程Id得到一个流程的情况 3 /// </summary> 4 /// <param name="flowId"></param> 5 /// <returns></returns> 6 public WorkflowServiceResponse GetFlowById(Guid flowId) 7 { 8 var wfsr = new WorkflowServiceResponse(); 9 try 10 { 11 var flow = _iWorkflowDb.GetFlows().SingleOrDefault(f => f.FlowId == flowId); 12 if (flow != null) 13 { 14 wfsr.ReturnEntity = flow; 15 wfsr.Success = true; 16 } 17 } 18 catch (Exception ex) 19 { 20 wfsr.Message = ex.ToString(); 21 } 22 return wfsr; 23 }
这样前后端都串起来了。
在IWorkflowDB接口定义里,GetFlows返回的是List<Flow>对象,所以这么做数据接口存在一定的性能问题,如果改成IQueryable<Flow>就能够返回Linq表达式,实现Lazy-Loaing的模式,但是Oracle不支持Linq查询,以后换EF看看......
大家注意到了WorkflowService类里面还有个IWorkflowMethods接口。对了,这个接口就是和其它系统交互的关键,定义如下:
1 public interface IWorkflowMethods 2 { 3 Person GetCurrentLoginPerson(); 4 IList<Person> GetPersonByCondition(SearchCriteria searchCriteria); 5 bool SendMail(Person person, string message); 6 bool SendMessage(Person person, string message); 7 string GetAutoCompleteValueByType(string autoCompleteType); 8 IList<string> GetUserRoleGroupNames(Person person); 9 }
这些方法分别是获取当前登录用户、根据条件获取应该审核流程的用户、调用原系统方法法邮件、发短信,用于表单处理中的自动填入用户姓名、职务等,获取用户所在的组(有些流程只有特定组可以申请)。
在其中一个系统中的实现方法如下:
1 public IList<Person> GetPersonByCondition(SearchCriteria searchCriteria) 2 { 3 var flowLaunchPerson = searchCriteria.FlowLaunchPerson; 4 string sql = string.Empty; 5 IList<Person> persons = new List<Person>(); 6 switch (searchCriteria.NextPersonWorkGroupName) 7 { 8 case ".....": 9 break; 10 case "xxx审核": 11 { 12 sql = string.Format(" jsgh in (select gh from VM_TUAN....ERGR where zbid in" + 13 " (select zbid from TUA....ELATIONSHIP where gh = '{0}' or xh = '{0}')" + 14 " and lv = 4 and zwname = '辅导员)') ", flowLaunchPerson.PersonId); 15 break; 16 } 17 case ".....审核": 18 { 19 sql = string.Format(" jsgh in (select gh from VM.....HERGR where zbid in" + 20 " (select zbid from TUA....IONSHIP where gh = '{0}' or xh = '{0}')" + 21 " and lv = 4 and zwname = '...') ", flowLaunchPerson.PersonId); 22 break; 23 }; 24 case ".....审核": 25 ........ 26 break; 27 default: 28 break; 29 } 30 31 var teachers = new B.....GetModelList(sql); 32 33 if (teachers.Count > 0) 34 { 35 foreach (var teacher in teachers) 36 { 37 Person person = new Person() 38 { 39 PersonId = teacher....., 40 PersonName = teacher.J...., 41 PersonEmail = teacher.E...., 42 }; 43 persons.Add(person); 44 } 45 } 46 else 47 { 48 throw new WorkFlowAuditPersonNotFoundException("没有找到审核对象!"); 49 } 50 return persons; 51 }
最后分享服务类中两个核心的方法
新建流程:
1 /// <summary> 2 /// 根据流程Id建立新的流程 3 /// </summary> 4 /// <param name="workflowAddStepParameter"></param> 5 /// <returns></returns> 6 public WorkflowServiceResponse CreateNewFlowInstance(WorkflowAddStepParameter workflowAddStepParameter) 7 { 8 var wfsr = new WorkflowServiceResponse(); 9 string message = string.Empty; 10 11 if (workflowAddStepParameter.Flow == null) 12 { 13 wfsr.Message = "参数错误!"; 14 } 15 else 16 { 17 var person = GetCurrentLoginPerson(); 18 19 var flowInstance = new FlowInstance(); 20 flowInstance.FlowInstantId = Guid.NewGuid(); 21 flowInstance.Flow = workflowAddStepParameter.Flow; 22 flowInstance.Creator = person; 23 flowInstance.CreateDate = DateTime.Now; 24 25 var flowInstanceStep = new FlowInstanceStep(); 26 flowInstanceStep.StepInstanceId = Guid.NewGuid(); 27 flowInstanceStep.PersonSignatures = new List<WorkflowPersonSignature>() 28 { 29 new WorkflowPersonSignature() 30 { 31 Person = person, 32 SignatureDate = DateTime.Now, 33 SignatureStatus = WorkflowConstant.SignatureStatus.Start, 34 } 35 }; 36 flowInstanceStep.FlowStep = workflowAddStepParameter.Flow.FlowSteps.Single(s => s.IsStartStep); 37 38 flowInstanceStep.WriteValues = workflowAddStepParameter.WritedValues; 39 flowInstanceStep.CreateDate = DateTime.Now; 40 flowInstanceStep.ProcessDate = DateTime.Now; 41 flowInstanceStep.FileList = workflowAddStepParameter.AttachFiles; 42 43 var flowInstanceStep2 = new FlowInstanceStep(); 44 flowInstanceStep2.CreateDate = DateTime.Now; 45 flowInstanceStep2.FlowStep = 46 workflowAddStepParameter.Flow.FlowSteps.Single( 47 f => f.PreviousStepId == workflowAddStepParameter.Flow.FlowSteps.Single(p => p.IsStartStep).StepId); 48 flowInstanceStep2.StepInstanceId = Guid.NewGuid(); 49 flowInstanceStep2.StepStatus = WorkflowConstant.SignatureStatus.Undeal; 50 51 var flowProcessPersons = 52 _iWorkflowMethods.GetPersonByCondition(new SearchCriteria() 53 { 54 CurrentLoginPerson = person, 55 FlowLaunchPerson = person, 56 NextPersonWorkGroupName = flowInstanceStep2.FlowStep.RightGroupTitle, 57 }); 58 59 var personSignatures = new List<WorkflowPersonSignature>(); 60 61 if (flowProcessPersons.Count == 0) 62 { 63 throw new WorkFlowAuditPersonNotFoundException(); 64 } 65 foreach (var flowProcessPerson in flowProcessPersons) 66 { 67 personSignatures.Add( 68 new WorkflowPersonSignature() 69 { 70 Person = flowProcessPerson, 71 SignatureStatus = WorkflowConstant.SignatureStatus.Undeal, 72 }); 73 SendMessages(person, flowProcessPerson, WorkflowConstant.SignatureStatus.Undeal); 74 } 75 flowInstanceStep2.PersonSignatures = personSignatures; 76 flowInstance.FlowStepInstances = new List<FlowInstanceStep>() 77 { 78 flowInstanceStep, 79 flowInstanceStep2 80 }; 81 82 try 83 { 84 wfsr.Success = _iWorkflowDb.SaveFlowInstance(flowInstance); 85 wfsr.ReturnEntity = flowInstance; 86 } 87 catch (Exception ex) 88 { 89 wfsr.Message = ex.ToString(); 90 } 91 } 92 return wfsr; 93 }
增加流程步骤:
1 public WorkflowServiceResponse AddFlowInstanceStep(WorkflowAddStepParameter workflowAddStepParameter) 2 { 3 var wfsr = new WorkflowServiceResponse(); 4 var flowInstance = workflowAddStepParameter.CurrentInstance; 5 6 if (flowInstance != null) 7 { 8 try 9 { 10 var person = GetCurrentLoginPerson(); 11 var currentStepIndex = flowInstance.FlowStepInstances.Count - 1 ; 12 //idempotent check 13 var flowInstanceInDb = GetFlowInstanceByInstanceId(flowInstance.FlowInstantId).ReturnEntity as FlowInstance; 14 if (flowInstanceInDb.FlowStepInstances.Count != flowInstance.FlowStepInstances.Count) 15 { 16 wfsr.Message = "您已经处理过该流程,请不要重复提交(或者该流程已经由其他老师处理完成)"; 17 return wfsr; 18 } 19 20 var currentPersonSignatures = flowInstance.FlowStepInstances[currentStepIndex].PersonSignatures; 21 //idempotent check 22 bool deal = false; 23 for (int i = 0; i < currentPersonSignatures.Count; i++) 24 { 25 if (currentPersonSignatures[i].Person.PersonId == person.PersonId) 26 { 27 if (currentPersonSignatures[i].SignatureStatus != WorkflowConstant.SignatureStatus.Undeal) 28 { 29 wfsr.Message = "该流程已经处理过"; 30 return wfsr; 31 } 32 flowInstance.FlowStepInstances[currentStepIndex].PersonSignatures[i].SignatureDate = 33 DateTime.Now; 34 flowInstance.FlowStepInstances[currentStepIndex].PersonSignatures[i].SignatureStatus = 35 workflowAddStepParameter.SignatureStatus; 36 flowInstance.FlowStepInstances[currentStepIndex].PersonSignatures[i].Memo = workflowAddStepParameter.Memo; 37 deal = true; 38 } 39 } 40 if (!deal) 41 { 42 wfsr.Message = "您已经处理过该流程,请不要重复提交(或者该流程已经由其他老师处理完成)"; 43 return wfsr; 44 } 45 46 flowInstance.FlowStepInstances[currentStepIndex].WriteValues = workflowAddStepParameter.WritedValues; 47 flowInstance.FlowStepInstances[currentStepIndex].ProcessDate = DateTime.Now; 48 49 switch (workflowAddStepParameter.SignatureStatus) 50 { 51 case WorkflowConstant.SignatureStatus.Passed: 52 { 53 if (flowInstance.FlowStepInstances[currentStepIndex].FlowStep.CounterSignatureMode == 54 WorkflowConstant.CounterSignatureMode.OneApprove) 55 { 56 flowInstance.FlowStepInstances[currentStepIndex].StepStatus = 57 WorkflowConstant.SignatureStatus.Passed; 58 } 59 else if (flowInstance.FlowStepInstances[currentStepIndex].FlowStep.CounterSignatureMode == 60 WorkflowConstant.CounterSignatureMode.AllApprove) 61 { 62 if ( 63 flowInstance.FlowStepInstances[currentStepIndex].PersonSignatures.All( 64 s => s.SignatureStatus == WorkflowConstant.SignatureStatus.Passed)) 65 { 66 flowInstance.FlowStepInstances[currentStepIndex].StepStatus = 67 WorkflowConstant.SignatureStatus.Passed; 68 } 69 else 70 { 71 flowInstance.FlowStepInstances[currentStepIndex].StepStatus = 72 WorkflowConstant.SignatureStatus.PartialPassed; 73 } 74 } 75 if (flowInstance.FlowStepInstances[currentStepIndex].StepStatus == 76 WorkflowConstant.SignatureStatus.Passed) 77 { 78 if (flowInstance.FlowStepInstances[currentStepIndex].FlowStep.IsLastStep) 79 { 80 flowInstance.FlowStatus = WorkflowConstant.SignatureStatus.Finish; 81 var lastStep = new FlowInstanceStep(); 82 lastStep.StepInstanceId = Guid.NewGuid(); 83 lastStep.CreateDate = DateTime.Now; 84 lastStep.FlowStep = new FlowStep() 85 { 86 StepName = "流程结束", 87 }; 88 lastStep.ProcessDate = DateTime.Now; 89 lastStep.StepStatus = WorkflowConstant.SignatureStatus.Finish; 90 flowInstance.FlowStepInstances.Add(lastStep); 91 } 92 else 93 { 94 var nextStep = new FlowInstanceStep(); 95 nextStep.StepInstanceId = Guid.NewGuid(); 96 nextStep.CreateDate = DateTime.Now; 97 nextStep.FlowStep = 98 flowInstance.Flow.FlowSteps.Single( 99 f => 100 f.PreviousStepId == 101 flowInstance.FlowStepInstances[currentStepIndex].FlowStep.StepId); 102 nextStep.StepStatus = WorkflowConstant.SignatureStatus.Undeal; 103 104 var flowProcessPersons = 105 _iWorkflowMethods.GetPersonByCondition(new SearchCriteria() 106 { 107 CurrentLoginPerson = _iWorkflowMethods.GetCurrentLoginPerson(), 108 FlowLaunchPerson = flowInstance.Creator, 109 NextPersonWorkGroupName = nextStep.FlowStep.RightGroupTitle, 110 }); 111 112 var personSignatures = new List<WorkflowPersonSignature>(); 113 114 if (flowProcessPersons.Count == 0) 115 { 116 throw new WorkFlowAuditPersonNotFoundException(); 117 } 118 foreach (var flowProcessPerson in flowProcessPersons) 119 { 120 personSignatures.Add( 121 new WorkflowPersonSignature() 122 { 123 Person = flowProcessPerson, 124 SignatureStatus = WorkflowConstant.SignatureStatus.Undeal, 125 }); 126 } 127 nextStep.PersonSignatures = personSignatures; 128 flowInstance.FlowStepInstances.Add(nextStep); 129 } 130 } 131 132 break; 133 } 134 case WorkflowConstant.SignatureStatus.Stopped: 135 flowInstance.FlowStepInstances[currentStepIndex].StepStatus = 136 WorkflowConstant.SignatureStatus.Stopped; 137 flowInstance.FlowStatus = WorkflowConstant.SignatureStatus.Stopped; 138 139 break; 140 case WorkflowConstant.SignatureStatus.RejectToFirstStep: 141 { 142 flowInstance.FlowStepInstances[currentStepIndex].StepStatus = 143 WorkflowConstant.SignatureStatus.RejectToFirstStep; 144 var nextStep = new FlowInstanceStep(); 145 nextStep.StepInstanceId = Guid.NewGuid(); 146 nextStep.CreateDate = DateTime.Now; 147 nextStep.FlowStep = 148 flowInstance.Flow.FlowSteps.Single( 149 f => f.IsStartStep); 150 nextStep.StepStatus = WorkflowConstant.SignatureStatus.Undeal; 151 152 var personSignatures = new List<WorkflowPersonSignature>(); 153 personSignatures.Add(new WorkflowPersonSignature() 154 { 155 Person = 156 flowInstance.FlowStepInstances.Single(f => f.FlowStep.IsStartStep) 157 .PersonSignatures[0].Person, 158 SignatureStatus = WorkflowConstant.SignatureStatus.Undeal 159 }); 160 161 nextStep.PersonSignatures = personSignatures; 162 flowInstance.FlowStepInstances.Add(nextStep); 163 164 break; 165 } 166 case WorkflowConstant.SignatureStatus.RejectToPreviousStep: 167 { 168 flowInstance.FlowStepInstances[currentStepIndex].StepStatus = 169 WorkflowConstant.SignatureStatus.RejectToPreviousStep; 170 171 var nextStep = new FlowInstanceStep(); 172 nextStep.StepInstanceId = Guid.NewGuid(); 173 nextStep.CreateDate = DateTime.Now; 174 nextStep.FlowStep = 175 flowInstance.Flow.FlowSteps.Single( 176 f => 177 f.StepId == 178 flowInstance.FlowStepInstances[currentStepIndex].FlowStep.PreviousStepId); 179 nextStep.StepStatus = WorkflowConstant.SignatureStatus.Undeal; 180 181 var flowProcessPersons = 182 _iWorkflowMethods.GetPersonByCondition(new SearchCriteria() 183 { 184 CurrentLoginPerson = _iWorkflowMethods.GetCurrentLoginPerson(), 185 FlowLaunchPerson = flowInstance.Creator, 186 NextPersonWorkGroupName = nextStep.FlowStep.RightGroupTitle, 187 }); 188 189 var personSignatures = new List<WorkflowPersonSignature>(); 190 191 if (flowProcessPersons.Count == 0) 192 { 193 throw new WorkFlowAuditPersonNotFoundException(); 194 } 195 foreach (var flowProcessPerson in flowProcessPersons) 196 { 197 personSignatures.Add( 198 new WorkflowPersonSignature() 199 { 200 Person = flowProcessPerson, 201 SignatureStatus = WorkflowConstant.SignatureStatus.Undeal, 202 }); 203 } 204 nextStep.PersonSignatures = personSignatures; 205 flowInstance.FlowStepInstances.Add(nextStep); 206 207 break; 208 } 209 default: 210 break; 211 212 } 213 214 flowInstance.LastDealDate = DateTime.Now; 215 216 wfsr.Success = _iWorkflowDb.SaveFlowInstance(flowInstance); 217 wfsr.ReturnEntity = flowInstance; 218 } 219 catch (Exception ex) 220 { 221 wfsr.Message = ex.ToString(); 222 } 223 } 224 return wfsr; 225 226 }
感觉用DDD的思想写程序还是蛮舒服的。(感谢Steven的指出,操纵流程类并没体现DDD思想。在操纵Form类里面的有的,代码没贴出)
下回讲一下前端。
谢谢大家!
本系列导航:
作者:thanks
微信:-
QQ:305380844
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。