现在应该讲主控制类了,为了不把系统弄得太复杂,所以就用一个类作为主要控制类(服务类),作为前端、后端、业务逻辑的控制类。
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类里面的有的,代码没贴出)
下回讲一下前端。
谢谢大家!
本系列导航: