文章地址: http://www.cnblogs.com/Ninputer/archive/2009/08/28/expression_tree1.htmlhtml
//定義一個表達式 ConstantExpression exp1 = Expression.Constant(1); ConstantExpression exp2 = Expression.Constant(2); BinaryExpression exp12 = Expression.Add(exp1, exp2); ConstantExpression exp3 = Expression.Constant(3); BinaryExpression exp123 = Expression.Add(exp12, exp3); //須要轉爲LambdaExpression 後,才能執行 LambdaExpression lambda = Expression.Lambda(exp123); Delegate func = lambda.Compile(); MessageBox.Show( func.DynamicInvoke(null).ToString()); //直接定義LambdaExpression ParameterExpression expA=Expression.Parameter(typeof(double),"a"); MethodCallExpression expCall = Expression.Call(null, typeof(Math).GetMethod("Sin"), expA); lambda = Expression.Lambda(expCall, expA); //這個是表達式字面量,自動從語言層面的表達式轉爲表達式樹。 這個特殊語法只適於Lambda表達式。是一種語法糖! Expression<Func<double, double>> exp = a => Math.Sin(a);
表達式樹最終是一個內存中樹狀結構的數據。能夠文本化,序列化、轉存、傳輸等等。
web
運行時分析表達式的邏輯express
序列化或者傳輸表達式c#
從新編譯成可執行的代碼數組
課後習題:ui
//表達式求值時,驗證表達式是否正確 LambdaExpression lambda = Expression.Lambda(expN, expA);//後面各題的表達式及參數傳入此, Delegate func = lambda.Compile(); MessageBox.Show(func.DynamicInvoke(10).ToString()); //調用時,注意參數要按順序傳入 //一、 -a ParameterExpression expA = Expression.Parameter(typeof(double), "a"); UnaryExpression expN = Expression.Negate(expA); //二、a+b*2 ParameterExpression expA = Expression.Parameter(typeof(double), "a"); ParameterExpression expB = Expression.Parameter(typeof(double), "b"); ConstantExpression exp2=Expression.Constant(2.0); BinaryExpression expb2 = Expression.Multiply(exp2, expB); BinaryExpression expab2 = Expression.Add(expA, expb2); //三、Math.Sin(x)+Math.Cos(y) ParameterExpression expx = Expression.Parameter(typeof(double), "x"); ParameterExpression expy = Expression.Parameter(typeof(double), "y"); MethodCallExpression expsin = Expression.Call(null, typeof(Math).GetMethod("Sin"), expx); MethodCallExpression expcos = Expression.Call(null, typeof(Math).GetMethod("Cos"), expy); BinaryExpression expAdd = Expression.Add(expsin, expcos); //四、new StringBuilder("hello") ConstantExpression exphello = Expression.Constant("hello"); NewExpression expNew = Expression.New(typeof(StringBuilder).GetConstructor(new Type[] { typeof(string) }), exphello);
以後這4個就不會手寫了,根聽說明,能夠用直接寫表達式字面量,而後反編譯出表達式來。我用這方法反編譯一下:spa
一、new int[] { a, b, a + b}code
「Expression<Func<int, int, int[]>> exp = (a, b) => new int[] { a, b, a + b };「反編譯的,仍是自身!原做者說「不過C#編譯器有時會使用一些做弊手法,聰明的你應該能找到繞過的手段……」 ,我不知道是什麼手段orm
二、a[i – 1] * ihtm
「Expression<Func<int[], int,int>> exp = (a, i) => a[i-1]*i;」反編譯爲:
Expression.Lambda<Func<int[], int, int>>( Expression.Multiply( Expression.ArrayIndex( //注意這用的方法 c1 = Expression.Parameter(typeof(int[]), "a"), Expression.Subtract( c2 = Expression.Parameter(typeof(int), "i"), Expression.Constant(1, typeof(int)) ) ), c2), new ParameterExpression[] { c1, c2 } );
三、a.Length > b | b >= 0
「Expression<Func<int[], int, bool>> exp = (a, b) => a.Length > b || b > 0;」反編譯爲:
ParameterExpression c1; ParameterExpression c2; //注意如何獲取數組長度。我本身寫時,試着: MemberExpression expLen = Expression.Field(expA, "Length") //結果是不對的。代表length不是一個普通字段 。 Expression<Func<int[], int, bool>> exp = Expression.Lambda<Func<int[], int, bool>>( Expression.OrElse( Expression.GreaterThan(Expression.ArrayLength(c1 = Expression.Parameter(typeof(int[]), "a")),c2 = Expression.Parameter(typeof(int), "b")), Expression.GreaterThan(c2, Expression.Constant(0, typeof(int))) ), new ParameterExpression[] { c1, c2 } );
四、new System.Windows.Point() { X = Math.Sin(a), Y = Math.Cos(a) }
「Expression<Func<double, Point>> exp = (a) => new Point() { X = (int)Math.Sin(a), Y = (int)Math.Cos(a) };」 稍加變形,反編譯後仍是自身!