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

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。

 

备注

 

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

 

 

posted on 2013-05-10 09:44  HackerVirus  阅读(198)  评论(0编辑  收藏  举报