国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

干貨!表達式樹解析"框架"(1)

2019-11-14 16:52:26
字體:
來源:轉載
供稿:網友

最新設計請移步 輕量級表達式樹解析框架Faller http://m.survivalescaperooms.com/blqw/p/Faller.html

 

關于我和表達式樹

  其實我也沒有深入了解表達式樹一些內在實現的原理,所以具體來說它到底是個什么東西我也不是很清楚,我的理解只是他是可以將'部分'委托構造成對象,方便我們對他進行解析; 雖然我沒有完全搞懂表達式樹,但這并不妨礙我使用它(如果以后有時間,我想我會更深入的去和它接觸一下)

Lamda + 表達式樹的性能瓶頸

  對于Lamda表達式樹我的感覺是又愛又恨

  書寫和閱讀方面,無疑是非常成功的,他大大的減少了書寫難度,增加了可讀性

  但另一方面,在程序的性能上又是如此的糟糕

  來看下面一個栗子:

static void Main(){    Where1(u => u.Name == "1");    Where2(u => u.Name == "1");}public static void Where1(ExPRession<Func<User, bool>> expr){}public static void Where2(Func<User, bool> expr){}

  栗子中的 Where1 和 Where2 兩個方法,唯一的不同,一個是委托,一個是表達式樹

  同樣運行Where1和Where2 一萬次,Where2是0ms,Where1是57ms

  也就是說從Func<User, bool>轉為Expression<Func<User, bool>>一萬次需要57ms

  這對于我這樣一個追求性能的人來說,實在是有點難受!

  到不至于不能接受,只有有點難受

  但從另一方面我也在考慮,為什么像這樣的lamda不能直接預編譯成Expression呢?期待微軟的優化吧~

偽框架

  為什么我的標題中的框架為帶有引號?

  因為我覺得這其實是一個偽框架

  但他確實能幫助我們更好的解析Expression對象,或許應該把他稱之為解決方案或是別的

  不過~管他呢!能用就行了

你應該了解的Expression

  剛才說了雖然我也沒有完全搞懂,但是有些東西還是應該知道的
比如:

  • 以Expression作為基類的子類一共有多少個
  • 他們分別是干什么的

  第一個問題比較簡單

  1. 現在在vs中敲下 System.Linq.Expressions.Expression
  2. 然后按F1
  3. 如果順利的話,你現在已經打開了"MSDN"
  4. 如果沒有的話就手動點一下吧
  5. 然后滾動到屏幕最下面

  

  好了這里看到的就是所有`public`的子類(其實沒有公開的還有更多)

  至于他們分別是干什么用的,每一個都有自己不同的用法,這里不可能一一說明了,下面的內容也只會涉及到一部分,其他就要自己慢慢研究了

  舉個栗子:

BinaryExpression ----表示包含二元運算符的表達式

最基礎的用法就是它的三個屬性Left ,Right ,NodeType 
Left 獲取二元運算的左操作數。
Right 獲取二元運算的右操作數。
NodeType 獲取此 Expression 的節點類型。
it = it.Name == "blqw"就是一個BinaryExpression
Left = it.Name
Right = "blqw"
NodeType = Equals

  大概就是這么一個意思吧

效果預覽

框架結構

  嗯.允許我還是叫他框架吧,畢竟聽上去比較高端大氣上檔次啊

  暫時是這樣

  • Parsers文件夾里面的是具體對應每一種表達式樹的解析的具體實現
  • ExpressionParser     表達式樹解析器抽象基類,實現IExpressionParser
  • ExpressionTypeCode   枚舉,枚舉了所有的類型的表達式樹
  • IExpressionParser    表達式樹解析器接口
  • Parser          調用解析器的靜態對象,也可以看作入口或工廠,根據表達式樹類型調用具體類
  • ParserArgs        解析器參數,在解析表達式樹的方法中保持傳遞,可以保存解析中所使用的參數和保存解析結果

代碼

    public class ParserArgs    {        public ParserArgs()        {            Builder = new StringBuilder();        }        public StringBuilder Builder { get; private set; }        public IList<ParameterExpression> Forms { get; set; }        public readonly string[] FormsAlias = { "it", "A", "B", "C", "D", "E" };    }
ParserArgs
IExpressionParser
    /// <summary> 表達式樹解析接口    /// </summary>    public interface IExpressionParser    {        void Select(Expression expr, ParserArgs args);        void Where(Expression expr, ParserArgs args);        void GroupBy(Expression expr, ParserArgs args);        void Having(Expression expr, ParserArgs args);        void OrderBy(Expression expr, ParserArgs args);        void Object(Expression expr, ParserArgs args);    }
    /// <summary> 表達式樹解析抽象泛型類    /// </summary>    public abstract class ExpressionParser<T> : IExpressionParser        where T : Expression    {        public abstract void Select(T expr, ParserArgs args);        public abstract void Where(T expr, ParserArgs args);        public abstract void GroupBy(T expr, ParserArgs args);        public abstract void Having(T expr, ParserArgs args);        public abstract void OrderBy(T expr, ParserArgs args);        public abstract void Object(T expr, ParserArgs args);        public void Select(Expression expr, ParserArgs args)        {            Select((T)expr, args);        }        public void Where(Expression expr, ParserArgs args)        {            Where((T)expr, args);        }        public void GroupBy(Expression expr, ParserArgs args)        {            GroupBy((T)expr, args);        }        public void Having(Expression expr, ParserArgs args)        {            Having((T)expr, args);        }        public void OrderBy(Expression expr, ParserArgs args)        {            OrderBy((T)expr, args);        }        public void Object(Expression expr, ParserArgs args)        {            Object((T)expr, args);        }    }
ExpressionParser
    /// <summary> 表達式類型枚舉    /// </summary>    public enum ExpressionTypeCode    {        /// <summary> 未知類型表達式        /// </summary>        Unknown = 0,        /// <summary> 空表達式 null        /// </summary>        Null = 1,        /// <summary> 表示包含二元運算符的表達式。        /// </summary>        BinaryExpression = 2,        /// <summary> 表示一個包含可在其中定義變量的表達式序列的塊。        /// </summary>        BlockExpression = 3,        /// <summary> 表示包含條件運算符的表達式。        /// </summary>        ConditionalExpression = 4,        /// <summary> 表示具有常量值的表達式。        /// </summary>        ConstantExpression = 5,        /// <summary> 發出或清除調試信息的序列點。 這允許調試器在調試時突出顯示正確的源代碼。        /// </summary>        DebugInfoExpression = 6,        /// <summary> 表示類型或空表達式的默認值。        /// </summary>        DefaultExpression = 7,        /// <summary> 表示動態操作。        /// </summary>        DynamicExpression = 8,        /// <summary> 表示無條件跳轉。 這包括 return 語句、break 和 continue 語句以及其他跳轉。        /// </summary>        GotoExpression = 9,        /// <summary> 表示編制屬性或數組的索引。        /// </summary>        IndexExpression = 10,        /// <summary> 表示將委托或 lambda 表達式應用于參數表達式列表的表達式。        /// </summary>        InvocationExpression = 11,        /// <summary> 表示一個標簽,可以將該標簽放置在任何 Expression 上下文中。         /// </summary>        LabelExpression = 12,        /// <summary> 描述一個 lambda 表達式。 這將捕獲與 .NET 方法體類似的代碼塊。        /// </summary>        LambdaExpression = 13,        /// <summary> 表示包含集合初始值設定項的構造函數調用。        /// </summary>        ListInitExpression = 14,        /// <summary> 表示無限循環。 可以使用“break”退出它。        /// </summary>        LoopExpression = 15,        /// <summary> 表示訪問字段或屬性。        /// </summary>        MemberExpression = 16,        /// <summary> 表示調用構造函數并初始化新對象的一個或多個成員。        /// </summary>        MemberInitExpression = 17,        /// <summary> 表示對靜態方法或實例方法的調用。        /// </summary>        MethodCallExpression = 18,        /// <summary> 表示創建新數組并可能初始化該新數組的元素。        /// </summary>        NewArrayExpression = 19,        /// <summary> 表示構造函數調用。        /// </summary>        NewExpression = 20,        /// <summary> 表示命名的參數表達式。        /// </summary>        ParameterExpression = 21,        /// <summary> 一個為變量提供運行時讀/寫權限的表達式。        /// </summary>        RuntimeVariablesExpression = 22,        /// <summary> 表示一個控制表達式,該表達式通過將控制傳遞到 SwitchCase 來處理多重選擇。        /// </summary>        SwitchExpression = 23,        /// <summary> 表示 try/catch/finally/fault 塊。        /// </summary>        TryExpression = 24,        /// <summary> 表示表達式和類型之間的操作。        /// </summary>        TypeBinaryExpression = 25,        /// <summary> 表示包含一元運算符的表達式。        /// </summary>        UnaryExpression = 26,    }
ExpressionTypeCode
    /// <summary> 解析器靜態對象     /// </summary>    public static class Parser    {        private static readonly IExpressionParser[] Parsers = InitParsers();        static IExpressionParser[] InitParsers()        {            var codes = Enum.GetValues(typeof(ExpressionTypeCode));            var parsers = new IExpressionParser[codes.Length];            foreach (ExpressionTypeCode code in codes)            {                if (code.ToString().EndsWith("Expression"))                {                    var type = Type.GetType(typeof(Parser).Namespace + "." + code.ToString() + "Parser");                    if (type != null)                    {                        parsers[(int)code] = (IExpressionParser)Activator.CreateInstance(type);                    }                }            }            return parsers;        }        /// <summary> 得到表達式類型的枚舉對象 </summary>        /// <param name="expr"> 擴展對象:Expression </param>        /// <returns> </returns>        public static ExpressionTypeCode GetCodeType(Expression expr)        {            if (expr == null)            {                return ExpressionTypeCode.Null;            }            if (expr is BinaryExpression)            {                return ExpressionTypeCode.BinaryExpression;            }            if (expr is BlockExpression)            {                return ExpressionTypeCode.BlockExpression;            }            if (expr is ConditionalExpression)            {                return ExpressionTypeCode.ConditionalExpression;            }            if (expr is ConstantExpression)            {                return ExpressionTypeCode.ConstantExpression;            }            if (expr is DebugInfoExpression)            {                return ExpressionTypeCode.DebugInfoExpression;            }            if (expr is DefaultExpression)            {                return ExpressionTypeCode.DefaultExpression;            }            if (expr is DynamicExpression)            {                return ExpressionTypeCode.DynamicExpression;            }            if (expr is GotoExpression)            {                return ExpressionTypeCode.GotoExpression;            }            if (expr is IndexExpression)            {                return ExpressionTypeCode.IndexExpression;            }            if (expr is InvocationExpression)            {                return ExpressionTypeCode.InvocationExpression;            }            if (expr is LabelExpression)            {                return ExpressionTypeCode.LabelExpression;            }            if (expr is LambdaExpression)            {                return ExpressionTypeCode.LambdaExpression;            }            if (expr is ListInitExpression)            {                return ExpressionTypeCode.ListInitExpression;            }            if (expr is LoopExpression)            {                return ExpressionTypeCode.LoopExpression;            }            if (expr is MemberExpression)            {                return ExpressionTypeCode.MemberExpression;            }            if (expr is MemberInitExpression)            {                return ExpressionTypeCode.MemberInitExpression;            }            if (expr is MethodCallExpression)            {                return ExpressionTypeCode.MethodCallExpression;            }            if (expr is NewArrayExpression)            {                return ExpressionTypeCode.NewArrayExpression;            }            if (expr is NewExpression)            {                return ExpressionTypeCode.NewArrayExpression;            }            if (expr is ParameterExpression)            {                return ExpressionTypeCode.ParameterExpression;            }            if (expr is RuntimeVariablesExpression)            {                return ExpressionTypeCode.RuntimeVariablesExpression;            }            if (expr is SwitchExpression)            {                return ExpressionTypeCode.SwitchExpression;            }            if (expr is TryExpression)            {                return ExpressionTypeCode.TryExpression;            }            if (expr is TypeBinaryExpression)            {                return ExpressionTypeCode.TypeBinaryExpression;            }            if (expr is UnaryExpression)            {                return ExpressionTypeCode.UnaryExpression;            }            return ExpressionTypeCode.Unknown;        }        /// <summary> 得到當前表達式對象的解析組件 </summary>        /// <param name="expr"> 擴展對象:Expression </param>        /// <returns> </returns>        public static IExpressionParser GetParser(Expression expr)        {            var codetype = GetCodeType(expr);            var parser = Parsers[(int)codetype];            if (parser == null)            {                switch (codetype)                {                    case ExpressionTypeCode.Unknown:                        throw new ArgumentException("未知的表達式類型", "expr");                    case ExpressionTypeCode.Null:                        throw new ArgumentNullException("expr", "表達式為空");                    default:                        throw new NotImplementedException("尚未實現" + codetype + "的解析");                }            }            return parser;        }        public static void Select(Expression expr, ParserArgs args)        {            GetParser(expr).Select(expr, args);        }        public static void Where(Expression expr, ParserArgs args)        {            GetParser(expr).Where(expr, args);        }        public static void GroupBy(Expression expr, ParserArgs args)        {            GetParser(expr).GroupBy(expr, args);        }        public static void Having(Expression expr, ParserArgs args)        {            GetParser(expr).Having(expr, args);        }        public static void OrderBy(Expression expr, ParserArgs args)        {            GetParser(expr).OrderBy(expr, args);        }        public static void Object(Expression expr, ParserArgs args)        {            GetParser(expr).Object(expr, args);        }    }
Parser

原理分解

首先將所有類型的表達式樹以枚舉的形式表現出來,1來是為了更直觀便于2是為了給他們編號

有了編號就可以方便的在數組或集合中給他們安排位置

初始化

在Parser類中,放置一個靜態字段

private static readonly IExpressionParser[] Parsers = InitParsers();

在InitParsers方法中,使用反射查找當前命名空間下名稱為 枚舉名 + Parser 的類,如果有則實例化,并根據枚舉的值,在集合中保存

ps:枚舉名 + Parser 作為解析器的命名規則,僅僅是為了方便反射調用,Parsers[0] = new xxx() 這個依然是可以由后期調用綁定的 

調用

然后提供一個方法,用于獲取當前表達式對象對應的枚舉值

        public static ExpressionTypeCode GetCodeType(Expression expr)        {            if (expr == null)            {                return ExpressionTypeCode.Null;            }            if (expr is BinaryExpression)            {                return ExpressionTypeCode.BinaryExpression;            }            if (expr is BlockExpression)            {                return ExpressionTypeCode.BlockExpression;            }            ...            ...            return ExpressionTypeCode.Unknown;        }

這里的方法我沒有選擇用反射來獲取枚舉值,還是基于對性能的考慮,這樣測試快5~10倍,有興趣的可以測試一下

        public static ExpressionTypeCode GetCodeType(Expression expr)        {            if (expr == null)            {                return ExpressionTypeCode.Null;            }            ExpressionTypeCode tc;            if (Enum.TryParse(expr.GetType().Name, out tc))            {                return tc;            }            return ExpressionTypeCode.Unknown;        }
反射代碼

得到枚舉之后,就可以按枚舉的值,從集合中獲取已經實例化的解析器為了方便調用,寫了一個方法GetParser

public static IExpressionParser GetParser(Expression expr){    var codetype = GetCodeType(expr);    var parser = Parsers[(int)codetype];    if (parser == null)    {        switch (codetype)        {            case ExpressionTypeCode.Unknown:                throw new ArgumentException("未知的表達式類型", "expr");            case ExpressionTypeCode.Null:                throw new ArgumentNullException("expr", "表達式為空");            default:                throw new NotImplementedException("尚未實現" + codetype + "的解析");        }    }    return parser;}

得到解析器之后,就可以做愛做的事了,

好了我也有點累了,先這樣吧

未完待續...

  干貨!表達式樹解析"框架"(2) 

  干貨!表達式樹解析"框架"(3)

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 新绛县| 磐石市| 平远县| 秦皇岛市| 兴安县| 永安市| 红桥区| 即墨市| 陇西县| 成都市| 会泽县| 伊通| 康马县| 邵阳县| 莱芜市| 霸州市| 灌云县| 双桥区| 阳泉市| 长宁县| 舟山市| 丹棱县| 石林| 邯郸县| 夏邑县| 饶平县| 大竹县| 恩施市| 常德市| 东港市| 嘉定区| 舟曲县| 资源县| 新余市| 晋州市| 建平县| 东宁县| 郯城县| 东阳市| 淮南市| 伊宁市|