现在应该讲主控制类了,为了不把系统弄得太复杂,所以就用一个类作为主要控制类(服务类),作为前端、后端、业务逻辑的控制类。

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类里面的有的,代码没贴出)

下回讲一下前端。

谢谢大家!

本系列导航:

  1. .net之工作流工程展示及代码分享(预告)
  2. .net之工作流工程展示及代码分享(一)工作流表单
  3. .net之工作流工程展示及代码分享(二)工作流引擎
  4. .net之工作流工程展示及代码分享(三)数据存储引擎
  5. .net之工作流工程展示及代码分享(四)主控制类
  6. .net之工作流工程展示及代码分享(五)前端交互

.net之工作流工程展示及代码分享(四)主控制类的更多相关文章

  1. .net之工作流工程展示及代码分享(三)数据存储引擎

    数据存储引擎是本项目里比较有特色的模块. 特色一,使用接口来对应不同的数据库.数据库可以是Oracle.Sqlserver.MogoDB.甚至是XML文件.采用接口进行对应: public inter ...

  2. .net之工作流工程展示及代码分享(二)工作流引擎

    在介绍完表单类的时候,接下来介绍工作流引擎,主要由四个类组成,分别是流程.流程步骤.流程实例.流程步骤实例类. 流程类: [Serializable] public class Flow { [Xml ...

  3. .net之工作流工程展示及代码分享(一)工作流表单

    Workflow表单的作用是能够在客户端进行表单设计,然后在流程中动态开放哪些输入框可以供用户填写. 在这里我扩展了一个常用的WebEditor工具——KindEditor,能够插入自定义的html符 ...

  4. .net之工作流工程展示及代码分享(预告)

    最近在帮公司做一个工作流程序模块,要求是可以嵌入到各种现有的程序中去.我想把自己制作的思路和过程同大家分享. 先上一张结构图: 由于该项目我一个人做,所以系统结构不能太复杂. 用到的技术主要有:DDD ...

  5. net之工作流工程展示及代码分享(记录)

    http://www.cnblogs.com/thanks/p/4183235.html

  6. JAVA基础代码分享--DVD管理

    问题描述 为某音像店开发一个迷你DVD管理器,最多可存6张DVD,实现碟片的管理. 管理器具备的功能主要有: 1.查看DVD信息. 菜单选择查看功能,展示DVD的信息. 2.新增DVD信息 选择新增功 ...

  7. 一款WP小游戏代码分享

    首先声明游戏是H5的代码,当然游戏部分不是我写的,感谢@LeZhi的分享,关于H5我还在学习,这里只是简单介绍一下如何把一款现成的H5游戏封装成一款WP游戏(当然也可以做成Windows游戏). 大家 ...

  8. Unity多媒体展示项目经验分享-ImageEffect+动态绑定

    Unity多媒体展示项目经验分享-ImageEffect+动态绑定+网络通信 <ignore_js_op> “海尔科技展墙”是去年年初我们为上海家电博览会制作的一个多媒体展项,有限的工期以 ...

  9. Java生鲜电商平台-生鲜售后系统的退款架构设计与代码分享

    Java生鲜电商平台-生鲜售后系统的退款架构设计与代码分享 说明:任何一个电商行业都涉及到退货与退款的问题,但是生鲜电商行业还设有一个显著的特点,那就是换货.在人性面前,各种各样的退货,退款,换货的售 ...

随机推荐

  1. osg 示例程序解析之osgdelaunay

    osg 示例程序解析之osgdelaunay 转自:http://lzchenheng.blog.163.com/blog/static/838335362010821103038928/ 本示例程序 ...

  2. linux系统网址

    主站:http://www.xitongzhijia.net/linux/ linux:http://www.xitongzhijia.net/linux/201603/69275.html (7.2 ...

  3. django manytomany

    转载:http://my.oschina.net/u/572994/blog/105280 例如有如下模型 models.py ? 1 2 3 4 5 6 7 from django.db impor ...

  4. 马克飞象 Markdown 使用和学习

    第三方学习网站 http://sspai.com/25137https://maxiang.io/ 使用工具:有道云笔记 https://note.youdao.com/ 新建时使用Mardown类型 ...

  5. soui使用wke时,设置js回调注意事项

    wke响应网页js函数调用时注意: 必须等网页加载完成后,才能通过SetJsFunc设置js函数与c++回调的对应.网页未加载就设置,不会响应c++函数. 示例代码: wkeJSData* data ...

  6. 更换Mac记录

    1. 重装Mac (1)格式化硬盘 (2)重装系统 (3)修改各种配置:电脑名.键盘等 2. 安装必要软件 (1)QQ.微信.网易云音乐等 (2)火狐.谷歌.SourceTree等 (3)安装Git ...

  7. nginx服务器配置

    nginx主要配置 #定义Nginx运行的用户和用户组user www www; #每个worker进程绑定到指定CPU ,均衡各CPU 负载worker_cpu_affinity 000000000 ...

  8. python学习道路(day6note)(time &datetime,random,shutil,shelve,xml处理,configparser,hashlib,logging模块,re正则表达式)

    1.tiim模块,因为方法较多我就写在code里面了,后面有注释 #!/usr/bin/env python #_*_coding:utf-8_*_ print("time".ce ...

  9. android逆向代码分析截图

  10. 网络编程学习笔记:linux下的socket编程

    socket是进程通信的一种方式,通过调用一些API可以实现进程间通信,建立连接以及收发信息的过程如下图所示: 这些函数的用法如下: 1.int socket(int protocolFamily, ...