在文章:這些.NET開源項目你知道嗎?讓.NET開源來得更加猛烈些吧!(第二輯)中,給大家初步介紹了一下Expression Evaluator驗證組件。那里只是概述了一下,並沒有對其使用和強大功能做深入研究,所以今天就通過一篇簡單的文章來預覽一下其強大的功能。本文曾在【原創】.NET開源表達式計算組件介紹與使用一文中介紹過一個.NET平台開源的表達式計算組件NCal。不過經過比較還是這個Expression Evaluator比較強大,雖然部分功能有重疊。也都能計算常規的數學表達式。這個組件的功能應該說更加強大吧。同時上次的文章中,也有網友提到了另外一個在github的.NET平台的表達式計算組件DynamicExpresso。
.NET開源目錄:【目錄】本博客其他.NET開源項目文章目錄
本文原文地址:.NET平台開源項目速覽(8)Expression Evaluator表達式計算組件使用入門
1.基本功能介紹
Expression Evaluator是一個輕量級的可以在運行時解析C#表達式的開源免費組件。表達式求值應該在很多地方使用,例如一些工資或者成本核算系統,就需要在后台動態配置計算表達式,從而進行計算求值。經過看源代碼,這組件是用到了一個Antlr3的開源工具,Antlr3是一個開源的,支持多平台的語法解析器。該組件目前還在更新中,所以值得關注。Expression Evaluator支持的特性有:
*支持算術運算符,支持關系運算符,以及邏輯運算符
*支持表達式分組和括號,以及遞增遞減運算符
*支持表達式屬性訪問以及動態類型,支持字符串的+運算
*支持數值類型的后綴d/f/m/l/u/ul、
*支持隱式表達式,以及成員訪問操作符(.)
*支持一些默認的類型,如double, float, char, string, DateTime, Convert, Math
*支持foreach循環
等等,更多功能還期待你的使用和發現。下面我們就將介紹該組件的幾個典型表達式求值的用途。
官方網站:http://csharpeval.codeplex.com/
2.數學表達式求值
數學表達式求值應該是最常見的,一般我們在應用程序中如果需要計算,是需要對參數進行類型轉換,然后在后台進行相應計算的。但是如果是計算一些符合的式子或者公式,特別是參數不一定的情況下,這個就比較麻煩,雖然也有解決辦好。但總歸是不好。那看看使用 Expression Evaluator的幾個簡單例子。
使用需要注意的是:需要直接引用ExpressionEvaluator.dll,另外Antlr3.Runtime.dll可以直接引用,也可以直接放到bin目錄中,否則會提示找不到依賴文件。以前看到過一個表達式組件也是使用了這個開源的語法分析器。
看看核心代碼,使用前引用主要的命名空間:using ExpressionEvaluator;
var expression = new CompiledExpression("1 + 2 + 3 + 4 + 5"); var result = expression.Eval(); Console.WriteLine(result);//結果 15
輸出結果是 15,很明顯就是2個過程,需要表達式,然后進行Eval分析計算即可。
另外在使用組件時,內部還默認注冊了很多.NET值類型,可以直接使用這些類型的靜態方法來進行操作。例如可以進行如下解析並執行:
var expression = new CompiledExpression("double.Parse('3.141592654')"); var result = expression.Eval(); Console.WriteLine(result); // 結果是:3.141592654
是可以直接執行double的Parse方法的。目前內置支持的類型:
object/Object,bool/Boolean,byte/Byte,char/Char,short/Int16,int/Int32,long/Int64,ushort/UInt16,uint/UInt32,ulong/UInt64,decimal/Decimal
double/Double,float/Single,string/String
至於布爾類型的判斷等也都支持,比較簡單,就不詳細說了。
下面就看看Expression Evaluator的其他用法。進行簡單數值計算,其他很多組件都能辦到。
3.注冊類型與范圍注冊類型的成員
在上面例子中,系統內部已經支持了一些數值類型,可以直接進行靜態函數的調用解析。但是實際中,我們的業務系統類型肯定千變萬化,要滿足動態計算的情況,顯然上面是不夠的。所以Expression Evaluator提供了這種非常給力的操作,將你的實例進行注冊后,在表達式中,可以直接使用注冊的名稱來訪問實例的成員變量,然后參與表達式的計算。這樣,很多復雜的動態計算功能基本都可以實現了。
看看下面這個例子,具體過程不詳細見解,我在注釋中寫全面一點,看代碼就可以理解了:
static void Test() { var v = new MyClass();//對象實例化 v.myExternalVar = 6;//字段賦值 //TypeRegistry是核心的類型注冊對象 var registry = new TypeRegistry(); //將上面的變量v進行注冊,以符號vars替代 registry.RegisterSymbol("vars", v); //表達式計算對象,仔細看里面的變量vars以及直接調用myExternalVar字段 var exp = new CompiledExpression("(vars.myExternalVar + 3) / 2 * 4.5 "); // 設置表達式的類型注冊對象為 registry,注意要在eval之前進行設置 exp.TypeRegistry = registry; Console.WriteLine(exp.Eval());//結果20.25,看看怎么來的? //表達式計算對象,仔細看里面的變量vars以及直接調用myExternalVar字段 var exp2 = new CompiledExpression("vars.getRandomNumber() + 3"); // 設置表達式的類型注冊對象為 registry,注意要在eval之前進行設置 exp2.TypeRegistry = registry; Console.WriteLine(exp2.Eval());//結果為8,5+3 }
上面的MyClass類型的代碼如下,很簡單:
/// <summary>自定義的實體或者業務類型</summary> public class MyClass { /// <summary>一個指定的double字段</summary> public double myExternalVar; //獲取double值的一個方法 public double getRandomNumber() { return 5;//假設默認返回5 } }
下面再看一下通過字符串訪問數組索引值的方法。
4.通過字符串動態訪問數組下標
和上面的例子有部分類似,開闊一下眼界吧,說明其使用是非常靈活的。為了便於演示,我們同樣構造一個MyClass2類,代碼如下:
public class MyClass2 { public string[] myExternalString; public int x; }
下面是訪問獲取字符串數組的代碼:
var v = new MyClass2(); v.myExternalString = new string[] { "Hello", "there", "World!" }; v.x = 2; var registry = new TypeRegistry(); registry.RegisterSymbol("v", v); var exp = new CompiledExpression("v.myExternalString[v.x/2]"); exp.TypeRegistry = registry; Console.WriteLine(exp.Eval());//結果there
5.資源
源代碼大家可以去官網下載最新的,還是老樣子,制作了一份CHM格式的幫助文檔。如果打不開的同學,記得右鍵,屬性,解除鎖定哦。曬圖: