動態建立生成lambd表達式

基於網上找的一段代碼進行修改,目前擴展了NotContains方法的實現express

using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Threading.Tasks; using ZW.CateringSystem.Common.ConvertHelper; namespace ZW.CateringSystem.Common.LinqHelper { #region 動態linq幫助類,鏈接符號,運算符號

    /// <summary>
    /// 動態linq工廠 /// </summary>
    public static class DynamicLinqFactory { /// <summary>
        /// 生成lambd表達式 /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="propertyStr"></param>
        /// <returns></returns>
        public static Expression<Func<TSource, bool>> CreateLambda<TSource>(string propertyStr) { // 設置自定義lanbd // 定義 lanbd 種子(p=> xxxxxx)中的 p
            var parameter = Expression.Parameter(typeof(TSource), "p"); var strArr = SpiltStrings(propertyStr); // 第一個判斷條件,固定一個判斷條件做爲最左邊
            Expression mainExpressin = ExpressionStudio(null, strArr.FirstOrDefault(x => x.LinkSymbol == LinkSymbol.Empty), parameter); // 將須要放置在最左邊的判斷條件從列表中去除,由於已經合成到表達式最左邊了
            strArr.Remove(strArr.FirstOrDefault(x => x.LinkSymbol == LinkSymbol.Empty)); foreach (var x in strArr) { mainExpressin = ExpressionStudio(mainExpressin, x, parameter); } return mainExpressin.ToLambda<Func<TSource, bool>>(parameter); } /// <summary>
        /// 組合條件判斷表達式 /// </summary>
        /// <param name="left">左邊的表達式</param>
        /// <param name="DynamicLinq"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static Expression ExpressionStudio(Expression left, DynamicLinqHelper DynamicLinq, ParameterExpression key) { Expression mainExpression = key; var properties = DynamicLinq.Left.Split('.'); // 從1開始,是不想用自定義種子,外層種子已經定義好了 // 暫時也不會有多個自定義種子,先這樣
            for (var i = 1; i < properties.Length; i++) { mainExpression = mainExpression.Property(properties[i]); } left = left == null
            // 若是左邊表達式爲空,則當前的表達式就爲最左邊
            ? ChangeOperationSymbol(DynamicLinq.OperationSymbol, mainExpression, DynamicLinq.Right) // 若是不爲空,則將當前的表達式鏈接到左邊
 : ChangeLinkSymbol(DynamicLinq.LinkSymbol, left, ChangeOperationSymbol(DynamicLinq.OperationSymbol, mainExpression, DynamicLinq.Right)); return left; } /// <summary>
        /// 將字符串裝換成動態幫助類(內含遞歸) /// </summary>
        public static List<DynamicLinqHelper> SpiltStrings(string propertyStr) { // 定義返回用List
            var outList = new List<DynamicLinqHelper>(); // 當最後已經沒有鏈接運算符的時候,進入該條件
            if (!propertyStr.Contains("&") & !propertyStr.Contains("|")) { // 當前的條件是不具有鏈接符號的
                var lastStr = propertyStr.Trim().Split(' '); if (lastStr.Length == 1) { outList.Add(new DynamicLinqHelper { LinkSymbol = LinkSymbol.Empty, Left = lastStr[0], Right = "", OperationSymbol = ChangeOperationSymbol("null") }); return outList; } outList.Add(new DynamicLinqHelper { LinkSymbol = LinkSymbol.Empty, Left = lastStr[0], Right = lastStr[2], OperationSymbol = ChangeOperationSymbol(lastStr[1]) }); return outList; } // 判斷當前 & | 哪一個符號在最後一個判斷邏輯內
            var key = propertyStr.LastIndexOf('&') > propertyStr.LastIndexOf('|') ? '&' : '|'; var nowStrArr = propertyStr.Substring(propertyStr.LastIndexOf(key)).Trim().Split(' '); outList.Add(new DynamicLinqHelper { LinkSymbol = ChangeLinkSymbol(nowStrArr[0]), Left = nowStrArr[1], OperationSymbol = ChangeOperationSymbol(nowStrArr[2]), Right = nowStrArr[3] }); // 將剩餘部分繼續切割
            propertyStr = propertyStr.Substring(0, propertyStr.LastIndexOf(key)).Trim(); // 遞歸 由後彺前
 outList.AddRange(SpiltStrings(propertyStr)); return outList; } /// <summary>
        /// 將字符串符號轉成運算枚舉符號 /// </summary>
        public static LinkSymbol ChangeLinkSymbol(string str) { // 這裏判斷連接符號 // 當連接符號爲Empty,則說明當前對象爲表達式的最左邊 // 若是一個表達式出現兩次連接符號爲空,則說明輸入的字符串格式有問題
            switch (str) { case "|": return LinkSymbol.OrElse; case "&": return LinkSymbol.AndAlso; default: return LinkSymbol.Empty; } } /// <summary>
        /// 將運算枚舉符號轉成具體使用方法 /// </summary>
        public static Expression ChangeLinkSymbol(LinkSymbol Symbol, Expression left, Expression right) { switch (Symbol) { case LinkSymbol.OrElse: return left.OrElse(right); case LinkSymbol.AndAlso: return left.AndAlso(right); default: return left; } } /// <summary>
        /// 將字符串符號轉成運算枚舉符號 /// </summary>
        public static OperationSymbol ChangeOperationSymbol(string str) { switch (str) { case "<": return OperationSymbol.LessThan; case "<=": return OperationSymbol.LessThanOrEqual; case ">": return OperationSymbol.GreaterThan; case ">=": return OperationSymbol.GreaterThanOrEqual; case "==": return OperationSymbol.Equal; case "!=": return OperationSymbol.NotEqual; case "Contains": return OperationSymbol.Contains; case "NotContains": return OperationSymbol.NotContains; case "null": return OperationSymbol.Null; } throw new Exception("OperationSymbol IS NULL"); } /// <summary>
        /// 將運算枚舉符號轉成具體使用方法 /// </summary>
        public static Expression ChangeOperationSymbol(OperationSymbol symbol, Expression key, object right) { if (symbol == OperationSymbol.Null) { return key; } // 將右邊數據類型強行轉換成左邊同樣的類型 // 二者若是Type不匹配則沒法接下去的運算操做,拋出異常
            object newTypeRight; if (right.ToString() == "null") { newTypeRight = null; } else { //判斷key.Type的類型,調用不一樣的方法進行轉換;
                var t = key.Type; newTypeRight = ConvertionExtensions.ChangeType(right, key.Type); } // 根據當前枚舉類別判斷使用那種比較方法
            switch (symbol) { case OperationSymbol.Equal: return key.Equal(Expression.Constant(newTypeRight)); case OperationSymbol.GreaterThan: return key.GreaterThan(Expression.Constant((newTypeRight))); case OperationSymbol.GreaterThanOrEqual: return key.GreaterThanOrEqual(Expression.Constant(newTypeRight)); case OperationSymbol.LessThan: return key.LessThan(Expression.Constant((newTypeRight))); case OperationSymbol.LessThanOrEqual: return key.LessThanOrEqual(Expression.Constant((newTypeRight))); case OperationSymbol.NotEqual: return key.NotEqual(Expression.Constant(newTypeRight)); case OperationSymbol.Contains: return key.Contains(Expression.Constant(newTypeRight)); case OperationSymbol.NotContains:   // 不包含
                    return Expression.Not(key.Contains(Expression.Constant(newTypeRight))); } throw new Exception("OperationSymbol IS NULL"); } } /// <summary>
    /// 動態linq幫助類 /// </summary>
    public class DynamicLinqHelper { [Display(Name = "")] public string Left { get; set; } [Display(Name = "")] public string Right { get; set; } [Display(Name = "運算符")] public OperationSymbol OperationSymbol { get; set; } [Display(Name = "鏈接符")] public LinkSymbol LinkSymbol { get; set; } } /// <summary>
    /// 鏈接符枚舉(未來可能會包含 括號 ) /// </summary>
    public enum LinkSymbol { [Display(Name = "&&")] AndAlso, [Display(Name = "||")] OrElse, [Display(Name = "")] Empty } /// <summary>
    /// 經常使用比較運算符 > , >= , == , < , <= , != ,Contains     /// </summary>
    public enum OperationSymbol { [Display(Name = "Contains")] Contains, [Display(Name = "NotContains")] NotContains, [Display(Name = ">")] GreaterThan, [Display(Name = ">=")] GreaterThanOrEqual, [Display(Name = "<")] LessThan, [Display(Name = "<=")] LessThanOrEqual, [Display(Name = "==")] Equal, [Display(Name = "!=")] NotEqual, [Display(Name = "null")] Null } #endregion

    /// <summary>
    /// Linq擴展 /// </summary>
    public static class ExpressionExtensions { #region 經常使用擴展方法

        /// <summary>
        /// 調用內部方法 /// </summary>
        public static Expression Call(this Expression instance, string methodName, params Expression[] arguments) { return Expression.Call(instance, instance.Type.GetMethod(methodName), arguments); } /// <summary>
        /// 獲取內部成員 /// </summary>
        public static Expression Property(this Expression expression, string propertyName) { // Todo:左邊條件若是是dynamic, // 則Expression.Property沒法獲取子內容 // 報錯在這裏,因爲expression內的對象爲Object,因此沒法解析到 // var x = (expression as IQueryable).ElementType;
            return Expression.Property(expression, propertyName); } /// <summary>
        /// 轉Lambda /// </summary>
        public static Expression<TDelegate> ToLambda<TDelegate>(this Expression body, params ParameterExpression[] parameters) { return Expression.Lambda<TDelegate>(body, parameters); } #endregion

        #region 經常使用運算符 [ > , >= , == , < , <= , != , || , && ]

        /// <summary>
        /// && /// </summary>
        public static Expression AndAlso(this Expression left, Expression right) { return Expression.AndAlso(left, right); } /// <summary>
        /// || /// </summary>
        public static Expression OrElse(this Expression left, Expression right) { return Expression.OrElse(left, right); } /// <summary>
        /// Contains /// </summary>
        public static Expression Contains(this Expression left, Expression right) { return left.Call("Contains", right); } /// <summary>
        /// > /// </summary>
        public static Expression GreaterThan(this Expression left, Expression right) { return Expression.GreaterThan(left, right); } /// <summary>
        /// >= /// </summary>
        public static Expression GreaterThanOrEqual(this Expression left, Expression right) { return Expression.GreaterThanOrEqual(left, right); } /// <summary>
        /// <         /// </summary>
        public static Expression LessThan(this Expression left, Expression right) { return Expression.LessThan(left, right); } /// <summary>
        /// <=         /// </summary>
        public static Expression LessThanOrEqual(this Expression left, Expression right) { return Expression.LessThanOrEqual(left, right); } /// <summary>
        /// == /// </summary>
        public static Expression Equal(this Expression left, Expression right) { return Expression.Equal(left, right); } /// <summary>
        /// != /// </summary>
        public static Expression NotEqual(this Expression left, Expression right) { return Expression.NotEqual(left, right); } #endregion } /// <summary>
    /// Queryable擴展 /// </summary>
    public static class QueryableExtensions { #region 自定義擴展Queryable

        /// <summary>
        /// Where擴展 /// </summary>
        public static IEnumerable<TSource> IWhere<TSource>(this IEnumerable<TSource> source, string linqStr) { return source.Where(DynamicLinqFactory.CreateLambda<TSource>(linqStr).Compile()); } /// <summary>
        /// FirstOrDefault擴展 /// </summary>
        public static TSource IFirstOrDefault<TSource>(this IEnumerable<TSource> source, string linqStr) { return source.FirstOrDefault(DynamicLinqFactory.CreateLambda<TSource>(linqStr).Compile()); } /// <summary>
        /// Count擴展 /// </summary>
        public static Int32 ICount<TSource>(this IEnumerable<TSource> source, string linqStr) { return source.Count(DynamicLinqFactory.CreateLambda<TSource>(linqStr).Compile()); } /// <summary>
        /// 自定義排序 /// </summary>
        public static IOrderedQueryable<TSource> ISort<TSource>(this IQueryable<TSource> source, string orderByProperty, bool asc) { string command = asc ? "OrderBy" : "OrderByDescending"; var type = typeof(TSource); var property = type.GetProperty(orderByProperty); var parameter = Expression.Parameter(type, "p"); var propertyAccess = Expression.MakeMemberAccess(parameter, property); var orderByExpression = Expression.Lambda(propertyAccess, parameter); var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExpression)); return (IOrderedQueryable<TSource>)source.Provider.CreateQuery<TSource>(resultExpression); } /// <summary>
        /// 自定義分頁 /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="nowPage"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public static IQueryable<TSource> IPaging<TSource>(this IQueryable<TSource> source, int nowPage, int pageSize) { return source.ISkip((nowPage - 1) * pageSize).ITake(pageSize); } /// <summary>
        /// 自定義Skip /// </summary>
        public static IQueryable<TSource> ISkip<TSource>(this IQueryable<TSource> source, int count) { return source.Provider.CreateQuery<TSource>(Expression.Call( // 類別
            typeof(Queryable), // 調用的方法
            "Skip", // 元素類別
            new Type[] { source.ElementType }, // 調用的表達樹
 source.Expression, // 參數
 Expression.Constant(count))); } /// <summary>
        /// 自定義Take /// </summary>
        public static IQueryable<TSource> ITake<TSource>(this IQueryable<TSource> source, int count) { return source.Provider.CreateQuery<TSource>(Expression.Call( // 類別
            typeof(Queryable), // 調用的方法
            "Take", // 元素類別
            new Type[] { source.ElementType }, // 調用的表達樹
 source.Expression, // 參數
 Expression.Constant(count))); } /// <summary>
        /// 自定義去重複 /// </summary>
        public static IEnumerable<TSource> IDistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { var seenKeys = new HashSet<TKey>(); return source.Where(element => seenKeys.Add(keySelector(element))); } /// <summary>
        /// 動態賦值 /// </summary>
        public static void CopyTo<T>(this object source, T target) where T : class, new() { if (source == null) return; if (target == null) { target = new T(); } foreach (var property in target.GetType().GetProperties()) { // 這裏能夠判斷一下當前屬性值是否爲空的 source.GetType().GetProperty(property.Name).GetValue(source, null)
                target.GetType().InvokeMember(property.Name, BindingFlags.SetProperty, null, target, new object[] { source.GetType().GetProperty(property.Name).GetValue(source, null) }); } } /// <summary>
        /// 移除特殊字段數據 /// </summary>
        public static void RemoveSpecialPropertyValue(this object source) { var properties = source.GetType().GetProperties(); foreach (var x in properties) { if (x.GetAccessors().Any(y => y.IsVirtual)) { source.GetType().GetProperty(x.Name).SetValue(source, null, null); } } } #endregion } } 
相關文章
相關標籤/搜索