UWInfo Blog
發表新文章
[Join] | [忘記密碼] | [Login]
搜尋

搜尋意見
文章分類-#Author#
[所有文章分類]
所有文章分類
  • ASP.NET (48)
  • ASP.NET2.0 (15)
  • ASP.NET4.0 (34)
  • JavaScript (49)
  • jQuery (26)
  • FireFox (4)
  • UW系統設定 (3)
  • SQL (39)
  • SQL 2008 (25)
  • mirror (4)
  • SVN (4)
  • IE (9)
  • IIS (20)
  • IIS6 (1)
  • 閒聊 (7)
  • W3C (6)
  • 作業系統 (9)
  • C# (24)
  • CSS (12)
  • FileServer (1)
  • HTML 5 (11)
  • CKEditor (3)
  • UW.dll (13)
  • Visual Studio (16)
  • Browser (8)
  • SEO (1)
  • Google Apps (3)
  • 網站輔助系統 (4)
  • DNS (5)
  • SMTP (4)
  • 網管 (11)
  • 社群API (3)
  • SSL (4)
  • App_Inventor (1)
  • URLRewrite (2)
  • 開發工具 (6)
  • JSON (1)
  • Excel2007 (1)
  • 試題 (3)
  • LINQ (1)
  • bootstrap (0)
  • Vue (3)
  • IIS7 (3)
  • foodpanda (2)
  • 編碼 (2)
  • 資安 (3)
  • Sourcetree (1)
  • MAUI (1)
  • CMD (1)
  • my sql (1)
  • API串接 (1)
最新回應
  • Newtonsoft.Json.JsonConvert.DeserializeObject 失敗的情況
    test...more
  • dotnet ef dbcontext scaffold
    ...more
  • [ASP.NET] 利用 aspnet_regiis 加密 web.config
    ...more
  • IIS ARR (reverse proxy) 服務安裝
    ...more
  • [錯誤訊息] 請加入 ScriptResourceMapping 命名的 jquery (區分大小寫)
    ...more
  • 用 Javascript 跨網頁讀取 cookie (Cookie cross page, path of cookie)
    ...more
  • 線上客服 - MSN
    本人信箱被盜用以致資料外洩,是否可以請貴平台予以協助刪除該信箱之使用謝謝囉...more
  • 插入文字到游標或選取處
    aaaaa...more
  • IIS 配合 AD (Active Directory) 認証, 使用 .Net 6.0
    太感謝你了~~~你救了我被windows 認證卡了好幾天QQ...more
  • PostgreSQL 的 monitor trigger
    FOR EACH ROW 可能要改為 FOR EACH STATEMENT ...more
標籤
  • 908
  • restore
  • 854
  • linq
  • User ORDER
  • SES
  • 420
  • end
  • free ssl
  • linux
  • 版本
  • intlTelInp
  • 大榮
  • 憑證匯出
  • encryption
  • 548
  • CK
  • orm
  • jquery
  • machineKey
  • -8926
  • 3482121121
  • @@yUZV3
  • 716
  • amazo
  • 吳東儒
  • javascript
  • response
  • 1
  • 4hew.com
  • aspnet_reg
  • Line[t]
  • Environmen
  • 436
  • window
  • 短網址
  • Contains,
  • 416
  • Domain
  • a
  • 6751
  • recovery O
  • complie
  • AD
  • Canvas
  • jpgschool
  • 162
  • aspx,
  • 刪除
  • Viewstate
搜尋 List.where 結果:
合併兩個 Expression -- Combining two expressions (Expression>)
找了很久,原來就在 梨子給的範例裡。

假設有兩個 expression: e1, e2

            var combineBody = Expression.AndAlso(e1.Body, Expression.Invoke(e2, e1.Parameters[0]));
            var finalExpression = Expression.Lambda<Func<TestClass, bool>>(combineBody, e1.Parameters).Compile();


同理,把上面的 AndAlso 換成 OrElse 就可以用 Or 合併。

即使只有兩行,還是不太可能背起來,所以當然要來做一下擴充

    public static class ExpressionExtension
    {
        public static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> e1, Expression<Func<T, bool>> e2)
        {
            var combineE = Expression.AndAlso(e1.Body, Expression.Invoke(e2, e1.Parameters[0]));

            return Expression.Lambda<Func<T, bool>>(combineE, e1.Parameters);
        }

        public static Expression<Func<T, bool>> OrElse<T>(this Expression<Func<T, bool>> e1, Expression<Func<T, bool>> e2)
        {
            var combineE = Expression.OrElse(e1.Body, Expression.Invoke(e2, e1.Parameters[0]));

            return Expression.Lambda<Func<T, bool>>(combineE, e1.Parameters);
        }
    }


使用範例:

            Expression<Func<Market, bool>> e1 = e => e.Is_Deleted == isDelete;

            Expression<Func<Market, bool>> e2 = e => string.IsNullOrEmpty(marketNo) || e.MarketNo.ToUpper().Contains(marketNo.ToUpper());

            return new
            {
                andMarkets = Ds.PageContext.ShopBandContext.Markets.Where(e1.AndAlso(e2)).ToList(),
                orMarkets = Ds.PageContext.ShopBandContext.Markets.Where(e1.OrElse(e2)).ToList(),
            };



 再補兩個擴充, 可以把多個 Expression 用 AndAlso 或 OrElse 串在一起:

        public static Expression<Func<T, bool>> OrElseAll<T>(this IEnumerable<Expression<Func<T, bool>>> exps)
        {
            if (exps.Count() == 1)
            {
                return exps.First();
            }

            var e0 = exps.First();

            var orExp = exps.Skip(1).Aggregate(e0.Body, (x, y) => Expression.OrElse(x, Expression.Invoke(y, e0.Parameters[0])));

            return Expression.Lambda<Func<T, bool>>(orExp, e0.Parameters);
        }

        public static Expression<Func<T, bool>> AndAlsoAll<T>(this IEnumerable<Expression<Func<T, bool>>> exps)
        {
            if (exps.Count() == 1)
            {
                return exps.First();
            }

            var e0 = exps.First();

            var orExp = exps.Skip(1).Aggregate(e0.Body, (x, y) => Expression.AndAlso(x, Expression.Invoke(y, e0.Parameters[0])));

            return Expression.Lambda<Func<T, bool>>(orExp, e0.Parameters);
        }


使用範例:

            Expression<Func<Market, bool>> q = e =>
            e.Is_Deleted == "N"
            && (string.IsNullOrEmpty(marketNo) || e.MarketNo.ToLower().Contains(marketNo.ToLower()))
            && (string.IsNullOrEmpty(isCombination) || isCombination != "Y" || e.TypeEnum == 200);

            if (!string.IsNullOrEmpty(name))
            {
                var nameList = name.Split(',').Select(e => e.Trim())
                    .Where(e => !string.IsNullOrEmpty(e));

                if (nameList.Any())
                {
                    q = q.AndAlso(nameList
                        .Select(s => (Expression<Func<Market, bool>>)(e => e.Name.ToLower().Contains(s.ToLower())))
                        .OrElseAll());
                }
            }






另外在 google,整理了 stackoverflow 幾篇文章之後得到的另一個方法,比較複雜, 不過可以讓人理解一下 Expression 比較底層的東西,也留下來參考一下。

    internal class MergeTool : ExpressionVisitor
    {
        private readonly ParameterExpression _parameter;

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return base.VisitParameter(_parameter);
        }

        internal MergeTool(ParameterExpression parameter)
        {
            _parameter = parameter;
        }

        public static Expression<Func<T, bool>> MergedExpression<T>(Expression<Func<T, bool>> e1, Expression<Func<T, bool>> e2)
        {
            ParameterExpression param = Expression.Parameter(typeof(T));

            BinaryExpression MergeBody = Expression.AndAlso(e1.Body, e2.Body);

            var ReplacedBody = (BinaryExpression)new MergeTool(param).Visit(MergeBody);

            return Expression.Lambda<Func<T, bool>>(ReplacedBody, param);
        }
    }

使用時要 Compile

            var mergedExpression = MergeTool.MergedExpression(e1, e2);

            var list = testList.Where(mergedExpression.Compile());

More...
Bike, 2022/8/13 下午 05:53:28
~ Uwinfo ~