在我們的.Net項目中,要使用到自訂公式功能,我們利用了IronPython的Lambda功能,可以方便的計算值,但是我們發現,如果運算式涉及的屬性發生改變時,公式必須重新計算,怎樣析運算式知道到底訪問了哪些屬性呢?
在我們的.Net項目中,要使用到自訂公式功能,我們利用了IronPython的Lambda功能,可以方便的計算值,但是我們發現,如果運算式涉及的屬性發生改變時,公式必須重新計算,怎樣析運算式知道到底訪問了哪些屬性呢?
仔細研究發現IronPython提供了這樣的功能:
以下為引用的內容: SystemState state = new SystemState(); CompilerContext context = new CompilerContext(); Parser p = Parser.FromString(state, context, "ActiveObject.Contact.Address + 'ds'"); IronPython.Compiler.Ast.Expression ex = p.ParseTestListAsExpression(); |
上面的程式碼分析了運算式:ActiveObject.Contact.Address + 'ds', 這裡用了Parser類可以分析出運算式,使用VS對象查看器,可以理解結果:
問題還沒有完全解決,我想結果有了,我總不能自己遞迴所有結構吧?哇,怎麼也有20多種類型,在看看,嗯,還有這個:
以下為引用的內容: class Program { static void Main(string[] args) { SystemState state = new SystemState(); CompilerContext context = new CompilerContext(); Parser p = Parser.FromString(state, context, "ActiveObject.Contact.Address + 'ds'"); IronPython.Compiler.Ast.Expression ex = p.ParseTestListAsExpression(); MyWalker w = new MyWalker(); ex.Walk(w); } } class MyWalker : AstWalker { public override bool Walk(FieldExpression node) { Console.WriteLine("Walk:{0},{1}", node.Name, node.Target); return base.Walk(node); } } |
Cool!!我重載的虛方法被調用了兩次,告訴我有2次欄位的訪問。
在.NET 3.5中提供了Lambda的結構描述類,但我是沒有找到動態編譯分析的類。看部落格園的朋友說:本來有個DynamicExpression的類提供了動態編譯功能,但是現在的.NET 3.5砍掉了,但是在Linq 101 samples中卻有原始碼,靠。
注意:本程式使用IronPython 的1.0版本,2.0版本的方法已經不同。 下面是2.0的代碼:
以下為引用的內容: class Program { static void Main(string[] args) { //引擎 IronPython.Hosting.PythonEngine engine = IronPython.Hosting.PythonEngine.CurrentEngine; //代碼單元 SourceCodeUnit unit = new SourceCodeUnit(engine, "ActiveObject.Contact.Address + 'ds'"); //上下文和選項 CompilerContext context = new CompilerContext(unit); IronPython.PythonEngineOptions option = new IronPython.PythonEngineOptions(); //分析運算式 Parser p = Parser.CreateParser(context,option); IronPython.Compiler.Ast.Expression ex = p.ParseExpression(); //遞迴尋找 MyWalker w = new MyWalker(); ex.Walk(w); } } class MyWalker : PythonWalker { public override bool Walk(MemberExpression node) { Console.WriteLine("Walk:{0},{1}", node.Name, node.Target); return base.Walk(node); } } |