表達式樹和泛型委托

作者: 姜敏  來源: 博客園  發布時間: 2009-05-22 09:56  閱讀: 3597 次  推薦: 0   原文鏈接   [收藏]  

什么是表達式樹?

  表達式樹又稱為表達式目錄樹,以數據形式表示語言級代碼。所有的數據都存儲在樹結構中,每個結點表示一個表達式(Expression)。要想手動生成表達式樹我們需要引用System.Linq.Expressions 命名空間,最重要的一個類是Expression,它是所有表達式的基類。例如:

  1:參數表達式:ParameterExpression,就是一個方法中的參數,例如 search(string key),key可以看成是一個參數表達式。

  2:二元表達式:BinaryExpression,例如a+b等。

  3:方法調用表達式:MethodCallExpression,例如:自定義LINQ提供程序中實現orderby 的操作:

MethodCallExpression orderByCallExpression = Expression.Call(
                
typeof(Queryable),
                
"OrderBy",
                
new Type[] { queryableData.ElementType, queryableData.ElementType
 },
                whereCallExpression,
                Expression.Lambda
<Func<stringstring>>(pe, new ParameterExpression
[] { pe }));

  4:常數表達式:ConstantExpression,例如數值5。

  5:字段或屬性表達式:MemberExpression,例如str.Length。Expression.Property(pe,   typeof(string).GetProperty("Length"));

  6:帶有條件運算的表達式:ConditionalExpression。

  7:描述lambda表達式:LambdaExpression

  8:一元運算符的表達式:UnaryExpression

  9:表達式和類型之間的相關操作:TypeBinaryExpression等等,它們都繼承Expression。

泛型委托:

  表達式樹經常與泛型委托一起使用,這里簡單介紹下什么是泛型委托。Func<(Of <(T, TResult>)>) 泛型委托:封裝一個具有一個參數并返回 TResult 參數指定的類型值的方法。如果想增加參數可以寫成Func<(Of <(T1,T2, TResult>)>) 等。這種方法比起傳統的顯示聲明委托的方法從代碼結構上要簡化不少,我們不用特意去申請一個delegate,所有的委托都可以用泛型委托來代替。這里簡單來實現一個算術表達式來說明泛型委托的好處。

  算術表達:(a+b)^b

  1:傳統的顯示申明委托方式。

  1):申明一個委托:

/// 
    /// (a+b)^b 委托
    
/// 
    /// para 1
    /// para 2
    /// 
    public delegate double PowerCompute(double num_1, double num_2);

  2):編碼委托對應的方法體

/// 
        /// (a+b)^b方法
        
/// 
        /// para 1
        /// para 2
        /// 
        public static  double GetPowerCompute(double num_1, double num_2)
        {
            
return Math.Pow((num_1 + num_2), num_2);
        }

  3):調用:

double dResult = 0;
            PowerCompute pc 
= GetPowerCompute;
            dResult 
= pc(22);
            Console.WriteLine(dResult.ToString());

  2:泛型委托實現:

  1):編碼委托對應的方法體,方法同上面代碼中第二步。

  2):調用

Func<double ,double ,double > fc=GetPowerCompute;
            dResult 
= fc(22);
            Console.WriteLine(dResult.ToString());

 

  表達式樹的執行:

  表達式樹和泛型委托:   這里實現一個簡單的表達式樹,實現(a+b)^b, 過程中需要知道以下三個比較重要的方法。

  1:Expression<(Of <(TDelegate>)>) :以表達式目錄樹的形式將強類型 lambda 表達式表示為數據結構。

  2: Expression.Lambda方法:創建一個表示 lambda 表達式的表達式目錄樹。

  3:Expression<(Of <(TDelegate>)>).Compile :將表達式目錄樹描述的 lambda 表達式編譯為可執行代碼。

  下面是(a+b)^b的表達式樹生成可執行代碼并且在客戶端進行調用的代碼:

ParameterExpression penum_1 = Expression.Parameter(typeof(double), "num_1");
            ParameterExpression penum_2 
= Expression.Parameter(typeof(double),
"num_2");
            BinaryExpression _be 
= Expression.Add(penum_1, penum_2);
            BinaryExpression _be2 
= Expression.Power(_be, penum_2);
            Expression
<Func<doubledoubledouble>> ef = Expression.Lambda<Func
<doubledoubledouble>>(_be2, new ParameterExpression[] { 

penum_1, penum_2 });
            Func
<doubledoubledouble> cf = ef.Compile();
            
return cf(num_1 ,num_2 );

下面是(a+b)^b的表達式樹的關系圖

表達式樹的修改:

  表達式目錄樹是不可變的,這意味著不能直接修改表達式目錄樹。若要更改表達式目錄樹,必須創建現有表達式目錄樹的一個副本,并在創建副本的過程中執行所需更改。您可以使用表達式目錄樹訪問器遍歷現有表達式目錄樹,并復制它訪問的每個節點。我們可以創建自定義類來繼承ExpressionVisitor,在自定義類中重定相應方式來達到修改表達式樹的目的。 

0
0
 
標簽:ASP.NET
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()