2010-08-20 125 views
1

我正在使用Reflection.Emit構建數學表達式分析器(例如2+2)。一個類採用中綴表達式(例如2+2),將其轉換爲後綴表達式(例如2 2 +),然後另一個類將該後綴表達式編譯爲IL並創建一個DynamicMethod。從那裏,可以評估表達式,就好像它是在編譯時創建的一樣,具有相似的速度。使用Reflection調用使用MethodInfo實例的方法。使用Reflection.Emit

該編譯器也支持隱式乘法,所以像x(2 + 2)目前計算爲x * (2 + 2)

,我試圖實現用戶自定義函數(例如f(x))。當我試圖區分隱式乘法(如上所示)和用戶定義的函數時,會出現問題。例如,如果用戶輸入x(5),我如何知道他們是否要將x乘以5,或者調用x函數的參數爲​​5

爲了解決這個問題,在前面的例子中,編譯器在IL流中插入if語句。它調用一個函數來確定函數是否以x的標識符定義。如果有的話,它會通過out變量和本地值將一個MethodInfo實例插入堆棧。

我的實際問題是,是否有可能執行一個方法使用堆棧上的MethodInfo實例在編譯過程中等價於調用IlGenerator.Emit(OpCodes.Call, MethodInfo)

謝謝。

+0

設計建議:使乘法明確,或具有不同的函數調用語法。含糊不清的語法導致錯誤/難以識別用戶錯誤。你知道標準的算術符號很糟糕,或者你不會轉換爲後綴,這是其中一個原因:) – 2010-08-20 03:27:57

回答

1

我意識到這一點的唯一方法可以讓你調用棧上的MethodInfo實例,方法是調用其上的Invoke方法。我相信你已經意識到這種可能性,但是你擔心它可能太慢了。我建議你嘗試一下並在壓力下計時。你可能會發現它對於你的目的來說足夠快。

如果不是,那麼您將不得不考慮如何重構您的設計,以便您不會傳遞MethodInfo實例。例如,您可以改爲傳遞託管函數指針。這些是ldftnldvirtftn指令返回的內容。然後,您可以使用calli指令來調用其中的一個。您將需要使用SignatureHelper class構建「呼叫站點描述」,其中calli期望作爲操作數。

+0

非常感謝!雖然我沒有在這裏使用確切的解決方案,但卻讓我有一種不同的處理方式。 – mgbowen 2010-08-20 04:16:14

+0

@nasufara:請考慮解釋您在單獨的答案中找到的解決方案,以便其他人可以從中受益。 – Timwi 2010-08-20 07:39:54

相關問題