最近想做一个OA相关的网站开发,一直都听说有workflow的东西,之前也断断续续学习过 Workflow Foundation 4.0,还是没有搞明白到底能够用它做什么

但还是觉得workflow在某种情形下应该可以适用,虽然还没有答案,网上搜楼了一通,发现一个workflow-core的东西,觉得挺有意思,遂停下来,琢磨一下,现分享与大家。

* 简介

workflow core的GitHub主页

如主页上介绍的,workflow core作为一个轻量级workflow引擎,可以嵌入到项目中,其底层是用.net standard 2.0开发,可以用来追踪长时间运行的任务状态,功能也比较强大,支持插件形式持久化,和多节点并行处理,貌似很牛。并且目前有给一个 Conductor 项目,就是使用workflow core作为内核的workflow服务器(原来运行workflow,需要单独的一个服务器啊),Conductor这里就不展开了。workflow core支持fluent语法,写起来也非常美观,虽然没有WF那样有图形化的操作界面,但感觉代码比较干净。

- 插播.Net Standard 2.0 简介

开始的时候不了解什么是.Net Standard 2.0,这篇文章讲得比较清楚,.Net Standard 与 .Net Framework关系还有这个.NET Core 2.0 是您的最好选择吗,原来微软为了统一.Net 的各种平台,出了一个.Net Standard 标准库,基于这个库开发的,可以应用于.net framework 4.6.1以上版本,也可以应用于.net core 2.0以上

了解了相关内容后,直接打开说明,照着例子走一遭了。

* 示例1

新建一个项目,指明使用.net framework 4.6.1以上,新建项目后,在Package Manager Console中,安装workflow core:Install-Package WorkflowCore,安装这个包会默认安装一系列的依赖包

可能由于版本的关系,还需要另外安装两个包:Microsoft.Extensions.Logging 和 Microsoft.Extensions.Logging.Debug。这样就可以按照Sample 01开始编写代码了

Sample01是一个helloworld,包含了几部分内容:

1. 构建StepBody,就是workflow中需要执行的内容,每个类继承自StepBody这个虚拟类,重载ExecutionResult Run(IStepExecutionContext context),这个函数中完成所需的工作

     public class HelloWorld : StepBody
{
private ILogger logger; public HelloWorld(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<HelloWorld>();
} public override ExecutionResult Run(IStepExecutionContext context)
{
Console.WriteLine("Hello world, workflow");
logger.LogInformation("Helloworld workflow"); return ExecutionResult.Next();
}
} public class GoodbyeWorld : StepBody
{
private ILogger logger; public GoodbyeWorld(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<GoodbyeWorld>();
} public override ExecutionResult Run(IStepExecutionContext context)
{
Console.WriteLine("Workflow, Goodbye");
logger.LogInformation("Goodbye workflow"); return ExecutionResult.Next();
}
} public class SleepStep : StepBody
{
private ILogger logger; public SleepStep(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger("SleepStep");
} public override ExecutionResult Run(IStepExecutionContext context)
{
Thread.Sleep(); logger.LogInformation("Sleeped"); return ExecutionResult.Next();
}
}

2. 构建workflow,实现IWorkflow接口,每个workflow有一个Id和一个Version,标明这个workflow的身份,这里通过两种方法构建了HelloWorkflow,

     public class HelloWorkflow : IWorkflow
{
public string Id => "HelloWorkflow"; public int Version => ; public void Build(IWorkflowBuilder<object> builder)
{
builder.StartWith(context =>
{
Console.WriteLine("Hello world");
return ExecutionResult.Next();
})
.Then(context =>
{
Thread.Sleep();
Console.WriteLine("sleeped");
return ExecutionResult.Next();
})
.Then(context =>
{
Console.WriteLine("Goodbye world");
return ExecutionResult.Next();
});
}
} public class HelloWorkflow2 : IWorkflow
{
public string Id => "HelloWorkflow"; public int Version => ; public void Build(IWorkflowBuilder<object> builder)
{
builder.StartWith<HelloWorld>()
.Then<SleepStep>()
.Then<GoodbyeWorld>();
}
}

HelloWorkflow

3. 万事俱备,准备让workflow运行起来。第一步当然是需要搭建service,Workflow Core通过Injection命名空间的ServiceCollection添加了Workflow相关的服务,对于有参数的StepBody,需要先通过service的AddTransient函数注册,这样才能正确的构造对象

         /// <summary>
/// 配置workflow
/// </summary>
/// <returns></returns>
private IServiceProvider ConfigureServices()
{
//setup dependency injection
IServiceCollection services = new ServiceCollection();
services.AddLogging();
services.AddWorkflow();
//services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow")); // 这些个构造函数带参数的,需要添加到transient中
services.AddTransient<HelloWorld>();
services.AddTransient<GoodbyeWorld>();
services.AddTransient<SleepStep>(); var serviceProvider = services.BuildServiceProvider(); //config logging
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
loggerFactory.AddProvider(new DebugLoggerProvider()); return serviceProvider;
}

构建Service

接下来,启动workflow 主机,并启动一次workflow,将整个窗体代码贴一下,这样比较清晰

 using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Logging.Debug;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WorkflowCore.Interface;
using WorkflowCore.Services;
using WorkFlowCoreTest.MyWorkflow; namespace WorkFlowCoreTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
IServiceProvider serviceProvider = null;
bool serviceStarted = false; public MainWindow()
{
InitializeComponent();
} private void StartWorkflow()
{ if (serviceProvider == null)
{
serviceProvider = ConfigureServices();
var host1 = serviceProvider.GetService<IWorkflowHost>(); host1.RegisterWorkflow<HelloWorkflow>();
host1.RegisterWorkflow<HelloWorkflow2>();
} var host = serviceProvider.GetService<IWorkflowHost>();
var wd = host.Registry.GetDefinition("HelloWorkflow"); // 如果host启动了,不能再次启动,但没有判断方法
if (!serviceStarted)
{
host.Start();
serviceStarted = true;
} // 启动workflow工作流
host.StartWorkflow("HelloWorkflow", , data: null); //
//host.StartWorkflow("HelloWorkflow");//, 2, data: null, 默认会启用版本高的
} private void StopWorkflow()
{
var host = serviceProvider.GetService<IWorkflowHost>(); host.Stop();
serviceStarted = false;
} /// <summary>
/// 配置workflow
/// </summary>
/// <returns></returns>
private IServiceProvider ConfigureServices()
{
//setup dependency injection
IServiceCollection services = new ServiceCollection();
services.AddLogging();
services.AddWorkflow();
//services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow")); // 这些个构造函数带参数的,需要添加到transient中
services.AddTransient<HelloWorld>();
services.AddTransient<GoodbyeWorld>();
services.AddTransient<SleepStep>(); var serviceProvider = services.BuildServiceProvider(); //config logging
var loggerFactory = serviceProvider.GetService<ILoggerFactory>();
loggerFactory.AddProvider(new DebugLoggerProvider()); return serviceProvider;
} private void startButton_Click(object sender, RoutedEventArgs e)
{
StartWorkflow();
} private void stopButton_Click(object sender, RoutedEventArgs e)
{
StopWorkflow();
}
}
}

就这样一个简单的Workflow Core例子就完成了,总体来说,还是很简单,清晰的。

workflow-core 简介的更多相关文章

  1. 酷学习笔记——ASP.NET Core 简介

    ASP.NET Core 简介 其实就是说酷好,不好好学,不学好,没饭吃. 新词汇:IoT,Internet of Things,网联网,微软物联网英文网站.微软物联网中文网站

  2. NET Core 简介

    1. 前言 .NET发行至今已经过了十四个年头.随着版本的不断迭代更新,.NET在Windows平台上的表现也是越来越好,可以说Windows平台上所有的应用类型.NET几乎都能完成. 只是成也Win ...

  3. [翻译] ASP.NET Core 简介

    ASP.NET Core 简介 原文地址:Introduction to ASP.NET Core         译文地址:asp.net core 简介           翻译:ganqiyin ...

  4. ASP.NET Core 简介 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 简介 - ASP.NET Core 基础教程 - 简单教程,简单编程 ← ASP.NET Core 基础教程 ASP.NET Core Windows 环境配置 → A ...

  5. 开源工作流引擎 Workflow Core 的研究和使用教程

    目录 开源工作流引擎 Workflow Core 的研究和使用教程 一,工作流对象和使用前说明 二,IStepBuilder 节点 三,工作流节点的逻辑和操作 容器操作 普通节点 事件 条件体和循环体 ...

  6. Workflow Core + asp.net core 5.0 实现简单审批工作流

    我们知道企业业务系统到处都可以审批工作流的,但也很少有像OA系统一样复杂多级多条件的审批工作流需要设计,所以我们需要一个轻量级的容易上手的workflow框架,通过GitHub,我发现danielge ...

  7. 第一节:EF Core简介和CodeFirst和DBFirst两种映射模式(以SQLite和SQLServer为例)

    一. EF简介 1. 定义 Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台的数据访问技术,它还是一种对象关系映射器(ORM),它使.NET 开发人员能够使用面向对 ...

  8. [.net core]简介(转)

    原文地址:https://docs.microsoft.com/zh-cn/dotnet/articles/core/ NET Core 是一个通用开发平台,由 Microsoft 和 GitHub  ...

  9. ASP.Net Core简介

    定义:一个经过精简的.模块化的.NET Framework子集,目的是为了跨平台..NET Core的类库叫做“CoreFX”,更精简的版本叫做“CoreCLR”. ASP.NET Core 是微软的 ...

  10. TDD in .NET Core - 简介

    本文很多内容来自选自TDD实例一书. 预备知识 最好有一些预备知识,例如xUnit,Moq,如何编写易于测试的代码,这些内容我都写了文章:https://www.cnblogs.com/cgzl/p/ ...

随机推荐

  1. P2731 骑马修栅栏 (欧拉路径)

    [题目描述] John是一个与其他农民一样懒的人.他讨厌骑马,因此从来不两次经过一个栅栏.你必须编一个程序,读入栅栏网络的描述,并计算出一条修栅栏的路径,使每个栅栏都恰好被经过一次.John能从任何一 ...

  2. vue中的scope

    在vue文件中的style标签上,有一个特殊的属性:scoped. 当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,也就是说,该样式只能适用于当前组件元素. 通过该属 ...

  3. python连接mariadb报错解决1045, "Access denied for user 'root'@'192.168.0.50' (using password: YES)

    [root@localhost ~]# python Python 2.7.5 (default, Apr 11 2018, 07:36:10) [GCC 4.8.5 20150623 (Red Ha ...

  4. 按字节读取txt文件缓存区大小设置多少比较好?

    读取 txt 文件常规写法有逐行读取和按照字节缓存读取,那么按照字节缓存读取时,设置缓存区多大比较好呢?百度了一下,没发现有说这个问题的,自测了一把,以事实说话. 常规读取方法如下: // 字节流读取 ...

  5. Mysql配置信息

    MySQL配置信息 MySQl基本 由MySQL AB公司开发,隶属于Oracle公司 默认端口:3306 超级用户:root MySQL目录结构 两种安装方式 ZIP安装 MSI安装(仅Window ...

  6. Window Server 2008 R2 FTP服务用户隔离

    Window Server 2008 R2 FTP服务用户隔离 原题:安装FTP服务,新建一个FTP站点,主目录为C:\ftproot,通过适当技术实现用户soft1 与soft2通过匿名方式登录FT ...

  7. ACM-ICPC 2015 Changchun Preliminary Contest J. Unknown Treasure (卢卡斯定理+中国剩余定理)

    题目链接:https://nanti.jisuanke.com/t/A1842 题目大意:给定整数n,m,k,其中1≤m≤n≤1018,k≤10, 然后给出k个素数,保证M=p[1]*p[2]……*p ...

  8. SQL 1 数据库 表的操作

    数据库:是按照数据结构来组织.存储和管理数据的建立在计算机存储设备上的仓库.一句话就是存储数据的仓库 数据库的分类:网络数据库.层级数据库.关系结构数据库. 倘若按照数据库的存储介质来分:关系型数据库 ...

  9. Ubuntu Server下MySql数据库备份脚本代码

    明: 我这里要把MySql数据库存放目录/var/lib/mysql下面的pw85数据库备份到/home/mysql_data里面,并且保存为mysqldata_bak_2012_04_11.tar. ...

  10. Zabbix分布式监控系统实践 自定义配置

    https://www.zabbix.com/wiki/templates/start 环境介绍OS: Ubuntu 10.10 Server 64-bitServers:zabbix-server: ...