WorkflowCore 编写与设计

发布时间:2023-05-19

WorkflowCore 使用指南

一、WorkflowCore 请假

WorkflowCore 作为一个基于 .NET Core 平台上的分布式流程处理框架,不仅支持 SQL Server 执行流程,还可以将内存数据持久化至 Redis、RabbitMQ、MongoDB 等第三方数据存储中心。它能够方便地为请假申请等一些列企业级业务提供处理方案。 下面是一个例子,展示了一个请假过程的 WorkflowCore 代码片段:

public class LeaveWorkflow : IWorkflow
{
    public string Id => "leave";
    public int Version => 1;
    public void Build(IWorkflowBuilder<object> builder)
    {
        builder
            .StartWith(context => ExecutionResult.Next())
            .While(data => ((LeaveData)data).IsNeedLeave, whileBuilder =>
            {
                whileBuilder
                    .Do(then => then.StartWith<ApplyLeave>()
                                     .Output(data => ((LeaveData)data).ApprovalResult, step => step.Result)
                                     .Then("IsLeaveApproved",
                                           conditionBuilder => conditionBuilder
                                                                     .When(data => ((LeaveData)data).ApprovalResult, true)
                                                                     .Then("Approved",
                                                                           thenBuilder => thenBuilder
                                                                                           .Do(context => Console.WriteLine("Approved successfully."))
                                                                           )
                                                                     .When(data => !((LeaveData)data).ApprovalResult, true)
                                                                     .Then("Rejected",
                                                                           thenBuilder => thenBuilder
                                                                                           .Do(context => Console.WriteLine("Rejected request."))
                                                                                 ));
            });
    }
}
public class ApplyLeave : StepBody
{
    public bool NeedLeave { get; set; }
    public DateTime StartTime { get; set; }
    public int DurationInDays { get; set; }
    public override ExecutionResult Run(IStepExecutionContext context)
    {
        Console.WriteLine("Applying leave...");
        var approvalResult = new Random().Next(1, 11) > 5;
        return ExecutionResult.Next(new LeaveData
        {
            IsNeedLeave = NeedLeave,
            StartTime = StartTime,
            DurationInDays = DurationInDays,
            ApprovalResult = approvalResult
        });
    }
}
public class LeaveData
{
    public bool IsNeedLeave { get; set; } = true;
    public DateTime StartTime { get; set; } = DateTime.Now;
    public int DurationInDays { get; set; } = 2;
    public bool ApprovalResult { get; set; }
}

二、WorkflowCore 书籍

为了更好地掌握 WorkflowCore 框架,需要一本详细的书籍来指导我们学习它的使用方法。《Pro WorkflowCore》 是 John Resig、 Jeremy Ashkenas 和 Michał Chodkowski-Janusz 编写的一本流程自动化开发指南。 笔者在阅读此书时,印象深刻之处在于其对实际业务场景的概述和分析,为我们理解 WorkflowCore 框架提供了了很好的指引。

三、WorkflowCore 流程设计器

WorkflowCore 流程设计器为使用者提供了一种非常方便的方案,使流程的设计变得非常直观。开发者可以利用工具手动绘制流程图,或者自动生成流程步骤列表。 示例代码片段如下:

var steps = new List<string>();
steps.Add(nameof(FindDog));
var descriptor = new WorkflowDefinition<YourData>()
    .StartWith<AssignDog>()
    .Then<string, FindDog>(
        nameof(FindDog),
        data => data.DogToFind,
        step => step
            .Input(step => step.DogName, data => data.DogToFind)
            .Output(data => data.DogLocation, step => step.Result)
    )
    .Then<NotifyDogLocation>(
        data => data.NotifyContact,
        step => step.Input(step => step.DogLocation, data => data.DogLocation)
    )
    .If(data => data.HasGivenUp,
        ifBuilder => ifBuilder
            .Do(then => then.StartWith<EnterLostDogMode>()
                           .Then(end => end.StartWith<NotifyContact>(
                               data => data.NotifyContact,
                               step => step.Input(step => step.Message, data => "Lost dog mode has been entered.")
                           ))
                           .Then(a => a.StartWith<EndWorkflow>()))
    );
var xml = new XmlWorkflowSerializer().Serialize(descriptor);

四、WorkflowCore 设计

WorkflowCore 的开发过程相对比较简单,它是开源框架,可以支持你快速编写自己的业务代码来实现各种流程形式。 为了制作自己的 WorkflowCore 进程,你可以从创建一个 Workflow 项目写起:

  1. 安装WorkflowCore Nuget 包。
  2. 在项目根目录下添加一个与 Workflow 名称一致的类,实现 IWorkflow 接口。
  3. 在 Workflow 类中使用 Workflow Builder 对象构建流程(起点和一系列步骤)。
  4. 在 Startup.ConfigureServices 方法中使用 WorkflowCore 并行添加 Workflow 服务。 下面是一个最简化的 WorkflowCore 样本代码:
public class SampleWorkflow : IWorkflow<MyDataClass>
{
    public string Id => "SampleWorkflow";
    public int Version => 1;
    public void Build(IWorkflowBuilder<MyDataClass> builder)
    {
        builder
            .StartWith(SayHello)
            .Then(DisplayMessage)
            .Then(End);
    }
    public void End(IStepExecutionContext<MyDataClass> context)
    {
        Console.WriteLine("Ending workflow...");
    }
    public ExecutionResult SayHello(IStepExecutionContext<MyDataClass> context)
    {
        Console.WriteLine("Hello World!");
        return ExecutionResult.Next();
    }
    public ExecutionResult DisplayMessage(IStepExecutionContext<MyDataClass> context)
    {
        Console.WriteLine(context.Workflow.Data.Message);
        return ExecutionResult.Next();
    }
}
public class MyDataClass
{
    public string Message { get; set; }
}

五、WorkflowCore 执行过程较长时间

WorkflowCore 的执行时间是相对较长的,主要是因为 Workflow 必须通过多个微服务来执行,在这个过程中,可能需要将数据存储到数据库中,与第三方系统交互,并启动其他服务。 因此,在使用 WorkflowCore 时,要注意对任务进行分割和异步处理。

六、WorkflowCore 设计器

WorkflowCore 的设计器使得开发人员能够在可视化的界面中更方便地 mockup 流程。这个设计器还支持添加一系列的步骤,包括 if/else 语句,分支和循环。 下面是一个 WorkflowCore 设计器的示例代码:

var design = new WorkflowDesign
{
    Inputs = new[]
    {
        new WorkflowInput
        {
            Key = "intputOne",
            Label = "Input Number One",
            Type = VariableType.Number
        }
    },
    Steps = new[]
    {
        new WorkflowStep
        {
            Id = "stepOne",
            Label = "Add Two",
            Inputs = new []
            {
                new WorkflowInputMapping
                {
                    SourceKey = "inputOne",
                    DestinationKey = "intOne"
                },
                new WorkflowInputMapping
                {
                    SourceKey = "stepTwoResult",
                    DestinationKey = "intTwo"
                }
            },
            Outputs = new []
            {
                new WorkflowOutputMapping
                {
                    SourceKey = "result",
                    DestinationKey = "stepOneResult"
                }
            },
            Settings = new WorkflowStepSettings
            {
                Type = "SampleType"
            }
        },
        new WorkflowStep
        {
            Id = "stepTwo",
            Label = "Increment",
            Outputs = new []
            {
                new WorkflowOutputMapping
                {
                    SourceKey = "result",
                    DestinationKey = "stepTwoResult"
                }
            }
        }
    }
};

七、WorkflowCore 实战

WorkflowCore 可以被用于各种负载流程,包括需求审批流程、订单和应用程序服务管理流程、甚至是调度生产设备的自动化流程等。 以下即是一个现实与实践密切相关的 WorkflowCore 示例代码:

public class SampleWorkflow : IWorkflow<MyDataClass>
{
    public string Id => "SampleWorkflow";
    public int Version => 1;
    public void Build(IWorkflowBuilder<MyDataClass> builder)
    {
        builder
            .StartWith<ReadData>()
                .Output(data => data.Value1, step => step.Value1)
                .Output(data => data.Value2, step => step.Value2)
            .Then<CalculateSum>()
                .Input(step => step.Value1, data => data.Value1)
                .Input(step => step.Value2, data => data.Value2)
                .Output(data => data.Result, step => step.Result)
            .Then<SendData>()
                .Input(step => step.Response, data => data.Result);
    }
}
public class MyDataClass
{
    public int Value1 { get; set; }
    public int Value2 { get; set; }
    public int Result { get; set; }
}
public class ReadData : StepBody
{
    public int Value1 { get; set; }
    public int Value2 { get; set; }
    public override ExecutionResult Run(IStepExecutionContext context)
    {
        Value1 = 2;
        Value2 = 5;
        return ExecutionResult.Next();
    }
}
public class CalculateSum : StepBody
{
    public int Value1 { get; set; }
    public int Value2 { get; set; }
    public int Result { get; set; }
    public override ExecutionResult Run(IStepExecutionContext context)
    {
        Result = Value1 + Value2;
        return ExecutionResult.Next();
    }
}
public class SendData : StepBody
{
    public int Response { get; set; }
    public override ExecutionResult Run(IStepExecutionContext context)
    {
        Console.WriteLine($"The result is: {Response}");
        return ExecutionResult.Next();
    }
}

八、WorkflowCore 图形化

WorkflowCore 支持图形化工具,可以将流程设计转化为一个流程定义 XML 文件。图形化工具使得我们能够更快地创建和修改我们的流程,同时也方便团队协作与沟通,并检测流程的正确性。 下面是一个 WorkflowCore 图形化工具设计的代码:

var def = new ProcessDefinition
{
    Id = "MyFirstWF",
    Steps = new List<ProcessStep>
    {
        new ProcessStep
        {
            Id = "step1",
            Name = "My First Step",  
            Type = StepType.Task,
            Data = new Dictionary<string, object>
            {
                {"TaskName", "My Task"}
            }
        },
        new ProcessStep
        {
            Id = "step2",
            Name = "My Second Step",
            Type = StepType.Control,
            Descendants = new List<string>
            {
                "step3"
            },
            Data = new Dictionary<string, object>
            {
                {"ControlFlowType", ControlFlowType.FullCondition}
            }
        },
        new ProcessStep
        {
            Id = "step3",
            Name = "My Third Step",
            Type = StepType.Task,
            Data = new Dictionary<string, object>
            {
                {"TaskName", "My Task 2"}
            }
        }
    }
};
var design = WorkflowDesignerParser.Parse(def);

九、WorkflowCore 多人审批

WorkflowCore 可以用于多人审批流程,这个过程就像简单的顺序审批过程一样,流程将会被视为改变状态的一系列步骤,每个步骤都由一个负责人来执行,然后再由其它人员来查看和审核。 示例代码如下:

public class ApprovalWorkflow : IWorkflow<ApprovalData>
{
    public string Id => "ApprovalWorkflow";
    public int Version => 1;
    public void Build(IWorkflowBuilder<ApprovalData> builder)
    {
        builder
            .StartWith(context => ExecutionResult.Next())
            .Then<AddSignature>()
                .Input(step => step.Signature, data => $"{data.Approver}: Approved")
                .Output(data => data.Signatures, step => (step.Signature, step.Name))
            .ForEach(data => data.Reviewers, iteration => iteration
                .Do(branch => branch
                    .StartWith<SendRequest>()
                        .Input(step => step.Request, data => $"Please review {data.DocumentName}")
                        .Input(step => step.Requester, data => data.Requester)
                    .Then(context =>
                    {
                        Console.WriteLine($"Request sent to {context.Workflow.Id}");
                        return ExecutionResult.Next();
                    })
                )
                .While(data => !data.Approved));
    }
}