• 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。

    备注

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

  • 相关阅读:
    [calss*="col-"]匹配类名中包含col-的类名,^以col-开头,$以col-结尾
    插件写法之脚本运行环境,mac和window检测
    @media only screen and (max-width:640px)中的问题,响应式布局
    webpack2的配置属性说明entry,output,state,plugins,node,module,context
    npm ERR! missing script: dev 报错解决
    [jshint] 'import' is only available in ES6 (use 'esversion: 6'). (W119) 提示import等ES6语法的jshint错误的,在代码前加一行 /* jshint esversion: 6 */
    Uncaught TypeError: (intermediate value)(...) is not a function 上一个方法结束没有加分号; 代码解析报错
    LeetCode 1. two sum
    redis集群尝试
    服务器搭建私人Git
  • 原文地址:https://www.cnblogs.com/happyframework/p/3070396.html
Copyright © 2020-2023  润新知