簡體   English   中英

Linq PredicateBuilder具有條件AND,OR和NOT過濾器

[英]Linq PredicateBuilder with conditional AND, OR and NOT filters

我們有一個使用LINQ to SQL的項目,為此我需要重寫幾個搜索頁面以允許客戶端選擇是否要執行 / 搜索。

我雖然使用PredicateBuilder重做LINQ查詢,但我認為這個工作得很好。 我實際上有一個包含我的謂詞的類,例如:

internal static Expression<Func<Job, bool>> Description(string term)
{
    return p => p.Description.Contains(term);
}

要執行搜索,我正在執行此操作(為簡潔起見,省略了一些代碼):

public Expression<Func<Job, bool>> ToLinqExpression()
{
    var predicates = new List<Expression<Func<Job, bool>>>();
    // build up predicates here

    if (SearchType == SearchType.And)
    {
        query = PredicateBuilder.True<Job>();
    }
    else
    {
        query = PredicateBuilder.False<Job>();
    }

    foreach (var predicate in predicates)
    {
        if (SearchType == SearchType.And)
        {
            query = query.And(predicate);
        }
        else
        {
            query = query.Or(predicate);
        }
    }
    return query;
}

雖然我對此感到滿意,但我有兩個顧慮:

  1. 評估SearchType屬性的if / else塊感覺它們可能是潛在的代碼味道。
  2. 客戶現在堅持能夠執行'而不是'/'或不執行'搜索。

為了解決第2點,我想我可以通過簡單地重寫我的表達式來做到這一點,例如:

internal static Expression<Func<Job, bool>> Description(string term, bool invert)
{
    if (invert)
    {
        return p => !p.Description.Contains(term);
    }
    else
    {
        return p => p.Description.Contains(term);
    }
}

然而,這感覺有點像一個kludge,這通常意味着那里有一個更好的解決方案。 任何人都可以推薦如何改善這一點? 我知道動態LINQ,但我真的不想失去LINQ的強類型。

如果您正在尋找更少的線路,您可以使用三元運算符替換if / else:

query = SearchType == SearchType.And ? PredicateBuilder.True<Job>() : PredicateBuilder.False<Job>();

   foreach (var predicate in predicates)
   {
        query = SearchType == SearchType.And ? query.And(predicate) : query.Or(predicate);
   }

對於'and not' / 'or not'部分! 操作員應該做的伎倆。

PD:你是否測試了foreach部分是否正確設置了謂詞?,據我所知,你正在構建將在稍后的時間點執行的表達式,所以你可能只有一個文字參考,只有最后一個設置謂詞在最后的迭代,這就是為什么你必須使用臨時變量來保存每次迭代的值。

編輯:如果你想否定一個程序性的表達式,這是一個棘手的,你可以嘗試類似的東西:

internal static Expression<Func<Job, bool>> Description(string term, bool invert)
        {
           return NegateExp<Func<Job, bool>>(p => p.Description.Contains(term), invert);
        }

而NegateExp方法將類似於:

public static Expression<TDelegate> NegateExp<TDelegate>(Expression<TDelegate> expression, bool inverse)
        {
            if (inverse)
            {
                return Expression.Lambda<TDelegate>(Expression.Not(expression.Body), expression.Parameters);
            }
            return expression;
        }

您可以查看此問題以獲取更多示例是否有任何方法可以否定謂詞?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM