NET:工作流中如何动态解析路由规则 之 T4 + 动态编译

背景

上篇文章中我介绍了如何用动态语言解释器执行路由规则,有很多朋友都给出了他们的选项,如下:

    1. 集成解释器(Iron、Javascript等)。
    2. 动态编译。
    3. 解析为Lamda表达式。
    4. 模板引擎。

因为我觉得动态编译很有意思,结合T4可能会更舒服,这篇文章就用这个思路重新实现一下如何解析路由规则。

思路

T4 + 动态编译 = 无限可能

如何使用动态编译解析这条规则(“LeaveDays>=5 && LeaveType=='病假'”)呢?思路有很多种,我立马想到的的有两种,将Leave的属性解析为某个方法的本地变量或方法所有类型的成员变量,下面就是动态编译后的方法:

1 public bool IsSatisfied(Leave entity)

2 {

3     var LeaveDays = entity.LeaveDays;

4     var LeaveType = entity.LeaveType;

5     return LeaveDays>=5 && LeaveType=="病假";

6 }

实现(代码下载

CSharpDynamicSpecification.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 Microsoft.CSharp;

 8 using System.CodeDom.Compiler;

 9 

10 namespace DynamicExpressionStudy

11 {

12     public sealed class CSharpDynamicSpecification<T> : IDynamicSpecification<T>

13     {

14         private string _expression;

15 

16         public CSharpDynamicSpecification(string expression)

17         {

18             _expression = expression;

19         }

20 

21         public bool IsSatisfied(T entity)

22         {

23             var dynamicInstance = this.CompileAndCreateInstance();

24 

25             var result = dynamicInstance

26                 .GetType()

27                 .GetMethod("IsSatisfied")

28                 .Invoke(dynamicInstance, new object[] { entity });

29 

30             return (bool)result;

31         }

32 

33         private object CompileAndCreateInstance()

34         {

35             CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider();

36 

37             CompilerParameters cp = new CompilerParameters();

38             cp.GenerateExecutable = false;

39             cp.GenerateInMemory = true;

40             cp.TreatWarningsAsErrors = false;

41             cp.ReferencedAssemblies.Add(Environment.CurrentDirectory + "\\DynamicExpressionStudy.exe");

42 

43             var templator = new DynamicSpecificationClassTemplate(typeof(T), _expression);

44             var sourceCode = templator.TransformText();

45 

46             CompilerResults cr = provider.CompileAssemblyFromSource(cp, sourceCode);

47 

48             return Activator.CreateInstance(cr.CompiledAssembly.GetType("DynamicExpressionStudy." + templator.TempClassName));

49         }

50     }

51 }

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             var leave = new Leave

14             {

15                 LeaveDays = 5,

16                 LeaveType = "病假"

17             };

18 

19             var specification = new CSharpDynamicSpecification<Leave>("LeaveDays>=5 && LeaveType==\"病假\"");

20 

21             var result = specification.IsSatisfied(leave);

22 

23             Console.WriteLine(result);

24         }

25     }

26 

27     public class Leave

28     {

29         public int LeaveDays { get; set; }

30 

31         public string LeaveType { get; set; }

32     }

33 }

运行结果为:true。

备注

这些解析路由规则的思路,可以用在其他任何需要动态计算的场合,如:薪酬公式、考核公式、考勤公式等。

 

你可能感兴趣的:(动态编译)