zoukankan      html  css  js  c++  java
  • 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。

    备注

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

  • 相关阅读:
    常见存储过程分页PK赛——简单测试分析常见存储过程分页速度
    简单的ASP.NET无刷新分页
    程序员45个好习惯
    手机应用兼职开发平台,欢迎有识之士参加...
    DotNetRemoting分布式安全部署(整理+原创)
    刚刚整理的截获SQL错误代码弹出提示信息类.
    485modbus通讯协议
    485通信
    ucoss在stm32上的移植
    使用OFFICE组件出问题环境配置
  • 原文地址:https://www.cnblogs.com/happyframework/p/3070396.html
Copyright © 2011-2022 走看看