擴充套件表示式
老外寫的一個不錯的擴充套件表示式的文章,原文地址:
Dynamically Composing Expression Predicates
Suppose you wanted to write a LINQ to SQL query that implemented a keyword-style. search. In other words, a query that returned rows whose description contained some or all of a given set of keywords.
We could proceed as follows:
[object Object]IQueryableSearchProducts (params string[] keywords) [object Object][object Object]
The temporary variable in the loop is required to avoid the outer variable trap, where the same variable is captured for each iteration of the foreach loop.
So far, so good. But this only handles the case where you want to match all of the specified keywords. Suppose instead, we wanted products whose description contains any of the supplied keywords. Our previous approach of chaining Where operators is completely useless! We could instead chain Union operators, but this would be inefficient. The ideal approach is to dynamically construct a lambda expression tree that performs an or-based predicate.
Of all the things that will drive you to manually constructing expression trees, the need for dynamic predicates is the most common in a typical business application. Fortunately, it’s possible to write a set of simple and reusable extension methods that radically simplify this task. This is the role of our PredicateBuilder class.
Using PredicateBuilder
Here's how to solve the preceding example with PredicateBuilder:
[object Object]IQueryableSearchProducts (params string[] keywords) [object Object][object Object]
PredicateBuilder Source Code
Here's the complete source:
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
public static class PredicateBuilder
...{
public static Expression
public static Expression
public static Expression
Expression
...{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast
return Expression.Lambda
(Expression.Or (expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression
Expression
...{
var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast
return Expression.Lambda
(Expression.And (expr1.Body, invokedExpr), expr1.Parameters);
}
}
PredicateBuilder is also shipped as part of LINQKit, a productivity kit for LINQ to SQL.
How it Works
The True and False methods do nothing special: they are simply convenient shortcuts for creating an Expression
var predicate = PredicateBuilder.True();
is just a shortcut for this:
Expression> predicate = c => true;
When you’re building a predicate by repeatedly stacking and/or conditions, it’s useful to have a starting point of either true or false (respectively). Our SearchProducts method still works if no keywords are supplied.
The interesting work takes place inside the And and Or methods. We start by invoking the second expression with the first expression’s parameters. An Invoke expression calls another lambda expression using the given expressions as arguments. We can create the conditional expression from the body of the first expression and the invoked version of the second. The final step is to wrap this in a new lambda expression.
More Examples
A useful pattern in writing a data access layer is to create a reusable predicate library. Your queries, then, consist largely of select and orderby clauses, the filtering logic farmed out to your library. Here's a simple example:
[object Object]public partial class Product [object Object][object Object]
We can extend this by adding a method that uses PredicateBuilder:
public partial class Product
...{
public static Expression
params string[] keywords)
...{
var predicate = PredicateBuilder.False
foreach (string keyword in keywords)
...{
string temp = keyword;
predicate = predicate.Or (p => p.Description.Contains (temp));
}
return predicate;
}
}
This offers an excellent balance of simplicity and reusability, as well as separating business logic from expression plumbing logic. To retrieve all products whose description contains “BlackBerry” or “iPhone”, along with the Nokias and Ericssons that are selling, you would do this:
[object Object]var newKids = Product.ContainsInDescription ("BlackBerry", "iPhone"); [object Object] [object Object]var classics = Product.ContainsInDescription ("Nokia", "Ericsson") [object Object] .And (Product.IsSelling()); [object Object]var query = [object Object] from p in Data.Products.Where (newKids.Or (classics)) [object Object] select p;
The And and Or methods in boldface resolve to extension methods in PredicateBuilder.
An expression predicate can perform. the equivalent of an SQL subquery by referencing association properties. So, if Product had a child EntitySet called Purchases, we could refine our IsSelling method to return only those products that have sold a minimum number of units as follows:
[object Object]public static Expression> IsSelling (int minPurchases) [object Object][object Object]
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4560/viewspace-2801248/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- kotlin 擴充套件(擴充套件函式和擴充套件屬性)Kotlin套件函式
- 【Kotlin】擴充套件屬性、擴充套件函式Kotlin套件函式
- Shell—擴充套件正規表示式(awk、sort、uniq、tr工具)套件
- 『忘了再學』Shell基礎 — 25、擴充套件正規表示式套件
- 使用Kotlin擴充套件函式擴充套件Spring Data案例Kotlin套件函式Spring
- Kotlin擴充套件函式Kotlin套件函式
- Z 函式(擴充套件KMP)函式套件KMP
- es6-函式擴充套件函式套件
- WCF擴充套件:行為擴充套件Behavior Extension套件
- 擴充正規表示式命令總結
- js陣列擴充套件用lamada表示式實現查詢是否存在JS陣列套件
- Kotlin-常用擴充套件函式Kotlin套件函式
- HIVE自定義函式的擴充套件Hive函式套件
- Kotlin基礎 — 擴充套件函式Kotlin套件函式
- Sanic 擴充套件套件
- ORACLE 擴充套件Oracle套件
- 擴充套件工具套件
- 擴充套件歐幾里得套件
- DOM擴充套件套件
- 擴充套件ACL套件
- Lua擴充套件套件
- 照片擴充套件套件
- 擴充套件篇套件
- disable or 擴充套件套件
- 擴充套件表套件
- Mybatis擴充套件MyBatis套件
- JMeter 擴充套件開發:擴充套件 TCP 取樣器JMeter套件TCP
- gcc對C語言的擴充套件:語句內嵌表示式(statement-embeddedexpression)GCC語言套件Express
- ES6之函式的擴充套件函式套件
- PHP的Sodium加密擴充套件函式了解PHP加密套件函式
- Kotlin的幾個擴充套件函式Kotlin套件函式
- JMeter擴充套件開發:自定義函式JMeter套件函式
- PHP的SPL擴充套件庫(四)函式PHP套件函式
- ?用Chrome擴充套件管理器, 管理你的擴充套件Chrome套件
- ASP.NET Core擴充套件庫之Http通用擴充套件ASP.NET套件HTTP
- php7安裝redis擴充套件和memcache擴充套件PHPRedis套件
- 分類擴充套件套件
- 新增php擴充套件PHP套件