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。

備注

這些解析路由規則的思路,可以用在其他任何需要動態計算的場合,如:薪酬公式、考核公式、考勤公式等。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM