();}}
复制
这里定义了一个HelloWorldWorkflow,其版本号为1,它有3个步骤:HelloWorld、ActiveWorld和GoodbyeWorld,会依次执行。
(2)定义三个继承自StepBody类的步骤类:
publicclassHelloWorld: StepBody
{public override ExecutionResult Run(IStepExecutionContext context){
Console.WriteLine("Hello World!");return ExecutionResult.Next();}}publicclassActiveWorld: StepBody
{public override ExecutionResult Run(IStepExecutionContext context){
Console.WriteLine("I am activing in the World!");return ExecutionResult.Next();}}publicclassGoodbyeWorld: StepBody
{public override ExecutionResult Run(IStepExecutionContext context){
Console.WriteLine("Goodbye World!");return ExecutionResult.Next();}}
复制
(3)ServiceCollection中注入Workflow-Core相关组件
privatestatic IServiceProvider ConfigureServices(){
IServiceCollection services =newServiceCollection();
services.AddLogging();// WorkflowCore需要用到logging service
services.AddWorkflow();var serviceProvider = services.BuildServiceProvider();return serviceProvider;}
复制
(4)在Program.cs的Main方法中获取到注入的host并执行工作流
publicstaticvoidMain(string[] args){var serviceProvider =ConfigureServices();var host = serviceProvider.GetService();
host.RegisterWorkflow();
host.Start();// Demo1:Hello World
host.StartWorkflow("HelloWorld");
Console.ReadKey();
host.Stop();}
复制
这里传入的是Workflow的Id,Workflow-Core会根据Id去自动匹配最新版本的对应Workflow,运行结果如下:
2.2 If语句
在工作流处理中,往往会有很多的条件判断,那么在Workflow-Core中也提供了直接的If功能,如下面这个IfStatementWorkflow所示:
publicclassIfStatementWorkflow: IWorkflow{public string Id=>"if-sample";public int Version=>1;publicvoidBuild(IWorkflowBuilder builder){
builder
.StartWith().If(data=> data.Counter <3).Do(then=> then
.StartWith().Input(step=> step.Message,data=>"Outcome is less than 3")).If(data=> data.Counter <5).Do(then=> then
.StartWith().Input(step=> step.Message,data=>"Outcome is less than 5")).Then();}}
复制
这个传递进来的MyData的定义如下:
publicclassMyData{public int Counter { get; set;}}
复制
当传递进来的MyData的Counter属性<3 或 <5时会有不同的分支进行逻辑的处理。
2.3 MySQL持久化支持
想要将工作流配置持久化到MySQL,只需以下两步:
(1)通过Nuget安装MySQL Provider包:
PM> Install-Package WorkflowCore.Persistence.MySQL
复制
(2)注入到ServiceCollection
services.AddWorkflow(x=> x.UseMySQL(@"Server=127.0.0.1;Database=workflow;User=root;Password=password;",true,true));
复制
一旦启动,你就会发现Workflow-Core自动帮你创建了很多表用于持久化工作流配置和实例。
2.4 计划任务和循环任务
Workflow-Core还集成了计划任务和循环任务的功能:
(1)计划任务:比如在工作流步骤中设置一个延迟5分钟执行的计划任务
builder
.StartWith(context=> Console.WriteLine("Hello")).Schedule(data=> TimeSpan.FromSeconds(5)).Do(schedule=> schedule
.StartWith(context=> Console.WriteLine("Doing scheduled tasks"))).Then(context=> Console.WriteLine("Doing normal tasks"));
复制
(2)循环任务:比如在工作流步骤中设置一个延迟5分钟进行的循环任务,知道Counter > 5才结束
builder
.StartWith(context=> Console.WriteLine("Hello")).Recur(data=> TimeSpan.FromSeconds(5),data=> data.Counter >5).Do(recur=> recur
.StartWith(context=> Console.WriteLine("Doing recurring task"))).Then(context=> Console.WriteLine("Carry on"));
复制
2.5 Saga支持
了解分布式事务方案的童鞋应该都知道Saga,在Workflow-Core中也有支持,这是一个十分有用的功能:
(1)比如:在创建一个客户信息之后,将其推送到Salesforce和ERP,如果推送过程中发生了错误,那么就通过重试进行补偿,并且重试有时间间隔。
builder
.StartWith().Then().OnError(WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10)).Then().OnError(WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10));
复制
(2)又比如:当Task2发生异常时,Workflow-Core会帮助执行UndoTask2 和 UndoTask1 帮你回滚数据以恢复状态。
builder
.StartWith().Saga(saga=> saga
.StartWith().CompensateWith().Then().CompensateWith().Then().CompensateWith()).OnError(Models.WorkflowErrorHandling.Retry, TimeSpan.FromMinutes(10)).Then();
复制
更多Saga示例,请参考:https://github.com/danielgerlag/workflow-core/tree/master/src/samples/WorkflowCore.Sample17
三、在ASP.NET Core中使用Workflow-Core
3.1 注入与初始化
(1)注入:使用AddWorkflow()扩展方法
publicvoidConfigureServices(IServiceCollection services){
services.AddWorkflow();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);}
复制
(2)初始化:
publicvoidConfigure(IApplicationBuilder app, IHostingEnvironment env){.......
app.UseWorkflow();}
复制
扩展方法如下:
publicstaticclassConfigureExtensions{publicstatic IApplicationBuilder UseWorkflow(this IApplicationBuilder app){var host = app.ApplicationServices.GetService();
host.RegisterWorkflow();
host.RegisterWorkflow();
host.Start();var appLifetime = app.ApplicationServices.GetService();
appLifetime.ApplicationStopping.Register(()=>{
host.Stop();});return app;}}
复制
这里需要注意的就是:将你要用到的所有Workflow都事先进行Register注册。
3.2 通过DI获取使用
在你想要用到的地方,无论是Controller还是Service,通过依赖注入获取到Host,并使用它:
[Route("api/[controller]")][ApiController]publicclassValuesController: ControllerBase
{private IWorkflowController _workflowService;publicValuesController(IWorkflowController workflowService){
_workflowService = workflowService;}// GET api/values[HttpGet]publicasync Task>Get(){await _workflowService.StartWorkflow("EdcWorkflow");returnnewstring[]{"EdcWorkflow v1"};}// GET api/values/5[HttpGet("{id}")]publicasync TaskGet(int id){await _workflowService.StartWorkflow("EdcDataWorkflow",newEdcData(){ Id = id });return"EdcDataWorkflow v1";}}
复制
这两个Workflow的定义如下:
publicclassEdcWorkflow: IWorkflow
{public string Id=>"EdcWorkflow";public int Version=>1;publicvoidBuild(IWorkflowBuilder