最近比較閑,年底了,項目也進入尾聲;每天就是維護一下系統,整理整理文檔,整理知識點,這樣才覺得有點意思;
問題
在使用Linq的where()查詢的時候,不知道大家是怎么動態組裝多個查詢條件時,是怎么做的?我是這樣做的,請看下面代碼;
方法一:
1.1 Expression的擴展類
public static class PredicateExtensions
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
{
var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression), expression1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
{
var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());//將一個委托或lambda表達式應用於參數表達式列表。
return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters);
}
}
1.2 實例化代碼
List<string> strList = new List<string>() { "鄭州","上海戶口", "魯山攬鍋菜", "南京酸菜魚" };
//傳統寫法
Func<string, bool> func = (t) => t.Length > 3&&t.Contains("魚");
var listA=strList.Where(func).ToList();
//使用擴展寫法
var expression=PredicateExtensions.True<string>();
expression = expression.And(t => t.Length > 3);
expression = expression.And(t => t.Contains("魚"));
var predicate = expression.Compile();
var listB = strList.Where(predicate).ToList();
方法二:合並兩個Expression表達式
2.1 表達式參數擴展類
public class MyExpressionVisitor:ExpressionVisitor
{
private readonly ParameterExpression _parameter;
public MyExpressionVisitor(ParameterExpression parameter)
{
_parameter = parameter;
}
public ParameterExpression Parameter
{
get { return _parameter; }
}
public Expression Nodify(Expression exp)
{
Expression e = this.Visit(exp);
return e;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return _parameter;
}
}
2.2 實例化代碼
int[] numbers = { 19, 25, 6, 8, 49, 7, 8, 0, 1, 47, 35, 30,29 };
//表達式一
ParameterExpression leftPara = Expression.Parameter(typeof(int), "n");
Expression a_con = Expression.Constant(13);
BinaryExpression a_binary = Expression.GreaterThan(leftPara, a_con);
var a_lambda = Expression.Lambda<Func<int, bool>>(a_binary,leftPara);
var a_result = a_lambda.Compile();
var a_list = numbers.Where(a_result).ToList();
//表達式二
ParameterExpression b_leftPara = Expression.Parameter(typeof(int), "n");
Expression b_con = Expression.Constant(30);
BinaryExpression b_binary = Expression.LessThanOrEqual(b_leftPara, b_con);
var b_lambda = Expression.Lambda<Func<int, bool>>(b_binary, b_leftPara);
var b_result = b_lambda.Compile();
var b_list = numbers.Where(b_result).ToList();
//合並兩個表達式
var vistor = new MyExpressionVisitor(leftPara);
Expression c_1 = vistor.Nodify(a_lambda.Body);
Expression c_2 = vistor.Nodify(b_lambda.Body);
BinaryExpression c_binary = Expression.AndAlso(c_1, c_2);
var c_lambda = Expression.Lambda<Func<int, bool>>(c_binary, leftPara);
var c_result = c_lambda.Compile();//編譯表達式
var c_list = numbers.Where(c_result).ToList();
方法二有點啰嗦,當時是用表達式樹來創建的;大家可以用匿名表達式簡單一點。但是在合並表達式的邏輯是,重新更改了一下表達式一和表達式二的參數,這樣在編譯的時候就可以通過了。
寫的不咋樣,日日精進吧。。。。
