.NET:工作流中如何动态解析路由规则,你肯定用得着
背景
做流程引擎最终避免不了一个问题:如何动态解析路由规则?
几乎所有的审批流程都要求支持条件路由,比如:请假天数大于xx天时某个领导审批,否则其它人审批。常见的解决方法有:一、动态编译;二、解释执行。这篇文章就讲解如何使用Javascript引擎解释执行。
思路
静态语言集成动态语言解释器这种模式,在业界已经有很多惯例,如:很多C++开发者都用Lua在运行时修改配置。因为我对Javascript比较熟悉,所以准备搜索一下Javascript的解释器。在NuGet中用Javascript关键字进行搜索,搜索到了第2页就找到了一个解释器,安装一下,准备尝试吧。
实现
代码下载:http://yunpan.cn/Q5jj9D2GKBZGh。
几乎我接触的所有解释器引擎提供的API都很相似,所以这里我直接贴代码了。
CondiationCalculator.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 using Jurassic; 8 9 namespace DynamicExpressionStudy 10 { 11 public static class CondiationCalculator 12 { 13 public static bool IsSatisfied(object entity, string expression) 14 { 15 var engine = new ScriptEngine(); 16 17 if (entity != null) 18 { 19 foreach (var property in entity.GetType().GetProperties()) 20 { 21 engine.SetGlobalValue(property.Name, property.GetValue(entity)); 22 } 23 } 24 25 return engine.Evaluate<bool>(expression); 26 } 27 28 public static bool IsSatisfied(Dictionary<string, object> variables, string expression) 29 { 30 var engine = new ScriptEngine(); 31 32 if (variables != null) 33 { 34 foreach (var variable in variables) 35 { 36 engine.SetGlobalValue(variable.Key, variable.Value); 37 } 38 } 39 40 return engine.Evaluate<bool>(expression); 41 } 42 } 43 }
Program.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DynamicExpressionStudy 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 { 14 var leave = new Leave 15 { 16 LeaveDays = 5, 17 LeaveType = "病假" 18 }; 19 20 var result = CondiationCalculator.IsSatisfied(leave, "LeaveDays>=5 && LeaveType=='病假'"); 21 22 Console.WriteLine(result); 23 } 24 25 { 26 var leave = new Dictionary<string, object> 27 { 28 { "LeaveDays", 5 }, 29 { "LeaveType", "病假" } 30 }; 31 32 var result = CondiationCalculator.IsSatisfied(leave, "LeaveDays>=5 && LeaveType=='病假'"); 33 34 Console.WriteLine(result); 35 } 36 } 37 } 38 39 public class Leave 40 { 41 public int LeaveDays { get; set; } 42 43 public string LeaveType { get; set; } 44 } 45 }
执行结果
备注
有朋友会说这种方式是不是速度会比较慢,确实是慢,不过考虑到一次只判断一个单据,还是可以接受的。
如果要求接近C#的速度,可以采用动态编译+缓存动态程序集的方式,我就用过一次。