學習表達式樹筆記

文章地址:  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) };」  稍加變形,反編譯後仍是自身!

相關文章
相關標籤/搜索