在我們的項目中,要使用到自訂公式功能,我們利用了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);
}
}