2012-03-23 51 views
7

我有一個situtaiton我讀商業邏輯,並用實際值替換變量,然後我需要評估它得到的結果。我目前使用bcParser來做到這一點,它適用於所有像Excel格式一樣寫入的邏輯。是否有可能爲動態if語句創建表達式樹?

拋給我的曲線球就是說,if條件不會像excel if(cond, true, false)相反,它會像C#那裏的if (cond) { true; } else { false;}一樣,這樣更有意義且易於維護。由於我事先用價值替換所有的變量,我所要做的就是評估它。目前,我正在通過將邏輯導出到c#方法並使用反射來解決此問題,我正在評估它,並且它也可以工作。

我想知道是否有任何其他選項,我不想爲每個條件編寫代碼,並且希望在運行時評估它。我想知道是否可以創建某種類型的令牌解析器並調用C#本地表達式評估並執行計算。我沒有去理解expresion樹,看起來有可能用這種方法。在我去那裏之前,我想知道它有可能嗎? 謝謝,

+3

表達式樹不會幫助您解析字符串。你可能想看看[CodeDom](http://msdn.microsoft.com/en-us/library/y2k85ax6.aspx)或[Rosalyn](http://msdn.microsoft.com/en-us/roslyn )。 – 2012-03-23 18:34:06

回答

5

是的!

關鍵是使用System.Linq.Expressions命名空間。你可以通過編程建立一個表達式樹,無論是在代碼中,還是通過修改解析器,然後將它編譯成一個Delegate。這個API編譯你的Delegate裏面的DynamicAssembly,這意味着當你完全解引用它們時,你的編譯表達式可以被垃圾回收器從內存中卸載。

這是一個很簡單的例子:

var b = true; 
Func<bool> condition =() => b; 
Action trueExpression =() => { Console.WriteLine(true); }; 
Action falseExpression =() => { Console.WriteLine(false); }; 

var e = Expression.Condition(
    Expression.Invoke(Expression.Constant(condition)), 
    Expression.Invoke(Expression.Constant(trueExpression)), 
    Expression.Invoke(Expression.Constant(falseExpression))); 

var λ = Expression.Lambda(e).Compile(); 

b = true; 
λ.DynamicInvoke(); 

b = false; 
λ.DynamicInvoke(); 

這將產生輸出:

True 
False 

了表達式被編譯成一個lambda可以是一個顯著的表現擊步,你會想爲你編譯的lambdas提出一個緩存策略。儘管如此,使用DynamicInvoke調用編譯的lambda非常快。幾乎與預編譯它一樣快。這種技術比使用CodeDom代碼生成(這需要整個另一個進程來編譯)要快得多,並且它具有生成可卸載程序集的主要優點。

對此的唯一限制是您無法使用此API創建類型。你必須限制自己的表達和陳述。這是相當強大的,但這是DLR的魔力。

+1

你如何獲得拉姆達符號?想! – usr 2012-03-24 19:13:13

+1

複製粘貼!這只是一個unicode角色。在C#中有效。 – 2012-03-27 15:46:06