为企业进行网站建设方案,免费推广网站排名,怀化建设公司网站,白银网站建设白银一、简介Dynamic Expresso是一个用.NET Standard 2.0编写的简单c#语句的解释器。Dynamic Expresso嵌入了自己的解析逻辑#xff0c;通过将其转换为.NET lambda表达式或委托来解释c#语句。使用Dynamic Expresso开发人员可以创建可编写脚本的应用程序#xff0c;无需编译即可执… 一、简介Dynamic Expresso是一个用.NET Standard 2.0编写的简单c#语句的解释器。Dynamic Expresso嵌入了自己的解析逻辑通过将其转换为.NET lambda表达式或委托来解释c#语句。使用Dynamic Expresso开发人员可以创建可编写脚本的应用程序无需编译即可执行.NET代码或者创建动态linq语句。语句是使用c#语言规范的子集编写的。全局变量或参数可以被注入并在表达式中使用。它不会生成程序集但会动态地创建表达式树。二、安装新建控制台项目DynamicExpressoResearch并通过NUGet添加DynamicExpresso.Core三、功能和特性返回值你可以解析并执行一个void类型没有返回值的表达式或者也可以返回任何有效的.NET类型。我们可以在解析表达式的时候指定期望的返回类型。static void EvalVoidExp(){var target new Interpreter();var t target.Eval(Program.empty(), new Parameter(Program, typeof(Program), new Program()));if (t null){Console.WriteLine(EvalVoidExp return value is null);}}//EvalVoidExp return value is nullstatic void EvalSpecReturnTypeExp(){var target new Interpreter();double result target.Evaldouble(Math.Pow(x, y) 5,new Parameter(x, typeof(double), 10),new Parameter(y, typeof(double), 2));Console.WriteLine(string.Format(We specify the return value type of the expression as double, return value is {0}, value type is {1}, result, result.GetType().FullName));int r target.Evalint(Math.Pow(x, y) 5,new Parameter(x, typeof(int), 10),new Parameter(y, typeof(int), 2));Console.WriteLine(string.Format(We specify the return value type of the expression as int, return value is {0}, value type is {1}, r, r.GetType().FullName));}//We specify the return value type of the expression as double, return value is 105, value type is System.Double//We specify the return value type of the expression as int, return value is 105, value type is System.Int32同时内置的表达式parser也可以自动感知表达式的返回类型static void AutoInferDataType(){var target new Interpreter();object r target.Eval(Math.Pow(x, y) 5,new Parameter(x, typeof(int), 10),new Parameter(y, typeof(int), 2));Console.WriteLine(string.Format(We do not specify the return value type of the expression, return value is {0}, value type is {1}, r, r.GetType().FullName));}2.变量(Variables)变量依附在Interpreter上相当于一个全局的控制参数可以应用到同一个Interpreter实例的所有表达式中
Interpreter提供了不同的方法可以实现传入不同类型的变量
SetVariable可以内置的原始类型及复杂的自定义数据类型static void SetParameter(){var target new Interpreter();target.SetVariable(rate, 0.8);object r target.Eval(price * rate,new Parameter(price, typeof(int), 200));Console.WriteLine(string.Format(The price of 200 with a 20% discount is {0}, r));r target.Eval(price * rate,new Parameter(price, typeof(int), 499));Console.WriteLine(string.Format(The price of 499 with a 20% discount is {0}, r));}The price of 200 with a 20% discount is 160The price of 499 with a 20% discount is 399.2SetFunction可以通过委托的方式传递函数static void SetFunction(){var target new Interpreter();Funcdouble, double, double pow (x, y) Math.Pow(x, y);target.SetFunction(pow, pow);object r target.Eval(pow(x, y),new Parameter(x, typeof(int), 10),new Parameter(y, typeof(int), 2));Console.WriteLine(string.Format(10 to the second power is {0}, r));r target.Eval(pow(x, y),new Parameter(x, typeof(int), 2),new Parameter(y, typeof(int), 4));Console.WriteLine(string.Format(2 to the fourth power is {0}, r));}//10 to the second power is 100//2 to the fourth power is 16SetExpression可以设置自定义的Expressionstatic void SetExpression(){var target new Interpreter();var rateExp Expression.Constant(0.8);target.SetExpression(rate, rateExp);object r target.Eval(price * rate,new Parameter(price, typeof(int), 200));Console.WriteLine(string.Format(The price of 200 with a 20% discount is {0}, r));r target.Eval(price * rate,new Parameter(price, typeof(int), 499));Console.WriteLine(string.Format(The price of 499 with a 20% discount is {0}, r));}3.参数(Parameters)参数需要每次执行的时候传递参数可以是任意的类型我们可以只解析一次表达式并通过不同的参数进行多次调用static void Invoke(){var target new Interpreter();var parameters new[] {new Parameter(x, typeof(int)),new Parameter(y, typeof(int))};var myFunc target.Parse(x y, parameters);myFunc.Invoke(23, 7);myFunc.Invoke(32, -2); }4.内置类型和自定义类型默认内部直接支持的数据类型有Object object Boolean bool Char charString stringSByte Byte byteInt16 UInt16 Int32 int UInt32 Int64 long UInt64 Single Double double Decimal decimal DateTime TimeSpanGuidMath Convert我们可以直接使用Interpreter.Reference来引用任何的.net类型static void ReferenceType(){var target new Interpreter().Reference(typeof(Uri));Console.WriteLine((target.Eval(typeof(Uri)) as Type).FullName);Console.WriteLine(target.Eval(Uri.UriSchemeHttp));}//System.Uri//http5.生成动态委托我们可以直接使用Interpreter.ParseAsDelegateTDelegate来解析表达式生成对应的委托然后可以直接调用对应的委托。class Customer{public string Name { get; set; }public int Age { get; set; }public char Gender { get; set; }}static void DynamicDelegate(){var customers new ListCustomer {new Customer() { Name David, Age 31, Gender M },new Customer() { Name Mary, Age 29, Gender F },new Customer() { Name Jack, Age 2, Gender M },new Customer() { Name Marta, Age 1, Gender F },new Customer() { Name Moses, Age 120, Gender M },};string whereExpression customer.Age 18 customer.Gender F index 0;var interpreter new Interpreter();FuncCustomer, int, bool dynamicWhere interpreter.ParseAsDelegateFuncCustomer, int, bool(whereExpression, customer, index);Console.WriteLine(customers.Where(dynamicWhere).Count());}6.生成lambda表达式我们可以使用Interpreter.ParseAsExpressionTDelegate解释表达式直接生成lambda表达式static void DynamicLambdaExpress(){var customers new ListCustomer {new Customer() { Name David, Age 31, Gender M },new Customer() { Name Mary, Age 29, Gender F },new Customer() { Name Jack, Age 2, Gender M },new Customer() { Name Marta, Age 1, Gender F },new Customer() { Name Moses, Age 120, Gender M },}.AsQueryable();string whereExpression customer.Age 18 customer.Gender F index 0;var interpreter new Interpreter();ExpressionFuncCustomer, int, bool dynamicWhere interpreter.ParseAsExpressionFuncCustomer, int, bool(whereExpression, customer, index);Console.WriteLine(customers.Where(dynamicWhere).Count());}7.支持的操作符CategoryOperatorsPrimaryx.y f(x) a[x] new typeofUnary - ! (T)xMultiplicative* / %Additive -Relational and type testing is asEquality !Logical ANDLogical ORLogical XOR^Conditional ANDConditional ORConditional?:AssignmentNull coalescing??8.文本标识CategoryOperatorsConstantstrue false nullReal literal suffixesd f mInteger literal suffixesu l ul luString/char 字符串或者字符类型中支持的转译 - single quote, needed for character literals - double quote, needed for string literals\ - backslash\0 - Unicode character 0\a - Alert (character 7)\b - Backspace (character 8)\f - Form feed (character 12)\n - New line (character 10)\r - Carriage return (character 13)\t - Horizontal tab (character 9)\v - Vertical quote (character 11)9.调用对象成员可以在表达式中直接调用对象实例的成员public class Student{public string Name { get; set; }public int Age { get; set; }public void Hello(){Console.WriteLine(string.Format(hello, my name is {0}, my age is {1}, Name, Age));}public static Student Instance(){return new Student() { Nameauto, Age 0};}}static void InvokTypeMember(){var s new Student() { Namemango, Age 30};var target new Interpreter().SetVariable(s, s);target.Reference(typeof(Student));Console.WriteLine(target.Eval(s.Hello()));Console.WriteLine(target.Eval(s.Name));Console.WriteLine(target.Eval(new Student().Hello()));Console.WriteLine(target.Eval(Student.Instance().Hello()));}同时可以支持扩展方法的调用
支持数组索引的调用
支持params数组
部分支持泛型static void InvokCollectionMember(){var x new int[] { 10, 30, 4 }; var target new Interpreter();target.SetVariable(x, x);Console.WriteLine(target.Eval(x.Count()));//Console.WriteLine(target.Eval(x.Countint()));Console.WriteLine(target.Eval(x[0]));var s new string[] {mango, is,test,params };target.SetVariable(s, s);Console.WriteLine(target.Eval(string.Join(\ \, s)));}10.Lambda表达式Dynamic Expresso只支持lambda表达式的部分功能为了减少对性能的影响默认是不开启Lambda表达式的解析的我们可以通过InterpreterOptions.LambdaExpressions 来启用这个功能static void EvalAsLambda(){var x new string[] { this, is, awesome };var options InterpreterOptions.Default | InterpreterOptions.LambdaExpressions; // enable lambda expressionsvar target new Interpreter(options).SetVariable(x, x);var results target.EvalIEnumerablestring(x.Where(str str.Length 5).Select(str str.ToUpper()));Console.WriteLine(results.First());}11.大小写默认情况下表达式是区分大小写的可以通过InterpreterOptions.CaseInsensitive或者InterpreterOptions.DefaultCaseInsensitive来忽略大小写static void IgnorCase(){var target new Interpreter(InterpreterOptions.CaseInsensitive);double x 2;var parameters new[] {new Parameter(x, x.GetType(), x)};Console.WriteLine(target.Eval(x, parameters));Console.WriteLine(target.Eval(X, parameters));}12.标识符探测Dynamic Expresso支持使用Interpreter.DetectIdentifiers来获取表达式中的变量标识符。static void DetectIdentifier(){var target new Interpreter();var detectedIdentifiers target.DetectIdentifiers(x y);Console.WriteLine(detectedIdentifiers.UnknownIdentifiers.First());Console.WriteLine(detectedIdentifiers.UnknownIdentifiers.Last());}13.默认数字类型默认情况下数字会被解析成int类型或者double类型但是在有些情况下例如财务中需要使用decimal类型的数字我们可以使用Interpreter.SetDefaultNumberType来设置static void SetNumberType(){var target new Interpreter();target.SetDefaultNumberType(DefaultNumberType.Decimal);Console.WriteLine(target.Eval(45).GetType().FullName);Console.WriteLine(target.Eval(10/3));}14.异常提供了ParseException作为解析表达式异常的基类同时提供了数个不同的具体的异常类例如UnknownIdentifierException, NoApplicableMethodException15.多线程Interpreter类可以在多线程中使用但是需要确保在多线程中只能调用get属性和Parse及Eval这些方法而对于初始化的一些设置(SetVariable/Reference)等只能在实例化对象的阶段调用如果我们需要使用不同的参数多次执行表达式最好的方式就是解析一次表达式并调用多次解析的结果16.安全性表达式中只能访问Reference中设置的类型以及设置的变量和参数的对象实例我们需要慎重考虑暴露哪些类给用户从1.3版本其默认禁用直接调用除了Type.Name的反射类方法17.功能局限Not every C# syntaxes are supported. Here some examples of NOT supported features:Multiline expressionsfor/foreach/while/do operatorsArray/list/dictionary initializationExplicit generic invocation (like method(arg))Lambda/delegate declaration (delegate and lamda are only supported as variables or parameters or as a return type of the expression)Array/list/dictionary element assignment (set indexer operator)Other operations on dynamic objects (only property, method invocation and index now are supported)18.使用场景Programmable applicationsAllow the user to inject customizable rules and logic without recompilingEvaluate dynamic functions or commandsLINQ dynamic query