在實際開發中,經常會遇到查詢條件不固定的情況:用戶可能只輸入姓名,也可能同時指定姓名、性別、年齡等多個欄位。傳統寫死 SQL 或 Lambda 的方式顯得死板且難以維護。本文介紹如何利用 System.Linq.Expressions 命名空間,在運行時動態構建 Lambda 表達式,實現靈活的動態查詢。
我們封裝一個泛型類別 ConstructLambda<T>,約束 T 為參考類型且擁有無參構造函數。該類別提供兩個核心方法:
GetAndLambdaExpression:以 AND 邏輯串聯多個條件GetOrLambdaExpression:以 OR 邏輯串聯多個條件public Expression<Func<T, bool>> GetAndLambdaExpression(Dictionary<string, string> dictionary)
{
// 1. 起始常量:True(AND 的單位元)
Expression expressionReturn = Expression.Constant(true);
// 2. 參數表達式:p => ...
ParameterExpression param = Expression.Parameter(typeof(T), "p");
foreach (string key in dictionary.Keys)
{
// 3. 取得屬性:p.Name
MemberExpression property = Expression.Property(param, typeof(T).GetProperty(key));
// 4. 呼叫 ToString():p.Name.ToString()
MethodCallExpression toStringCall = Expression.Call(property, typeof(T).GetMethod("ToString"));
// 5. 建立常數:值
ConstantExpression constant = Expression.Constant(dictionary[key]);
// 6. 比較:p.Name.ToString() == "JT"
BinaryExpression equal = Expression.Equal(toStringCall, constant);
// 7. 累積 AND
expressionReturn = Expression.And(expressionReturn, equal);
}
// 8. 封裝成 Lambda<T, bool>
return Expression.Lambda<Func<T, bool>>(expressionReturn, param);
}
GetOrLambdaExpression 邏輯類似,僅將起始常量改為 false、累積運算改為 Expression.Or。
public class Person
{
public string Name { get; set; }
public string Sex { get; set; }
public int Age { get; set; }
public DateTime Birthday { get; set; }
}
var dict = new Dictionary<string, string>
{
{"Name", "JT"}, {"Sex", "男"}, {"Age", "20"}, {"Birthday", "02/02/2008"}
};
| 場景 | 方法 | 生成的 Lambda 表達式 |
|---|---|---|
| 無條件 | AND | p => True |
| OR | p => False |
|
| 多條件 | AND | p => ((((True And p.Name.ToString() == "JT") And p.Sex.ToString() == "男") And p.Age.ToString() == "20") And p.Birthday.ToString() == "02/02/2008") |
| OR | p => ((((False Or p.Name.ToString() == "JT") Or p.Sex.ToString() == "男") Or p.Age.ToString() == "20") Or p.Birthday.ToString() == "02/02/2008") |
Expression<Func<T, bool>> 可直接傳給 Where,由提供者翻譯為 SQL。NullReferenceException。PropertyType 動態選擇 Expression.Equal、Expression.GreaterThan 等運算子。Func<T, bool> 或表達式樹本身。動態構建 Lambda 表達式讓查詢邏輯從「寫死」走向「配置化」,極大提升系統靈活度。掌握 System.Linq.Expressions 是進階 .NET 開發者的必修課,歡迎在留言區交流更多實戰技巧。