所以,鑑於這是一個IQueryable
,而不是IEnumerable
,你需要操縱表達式,而不是函數。首先,我們將定義有各運營商的字符串版本並將其映射到表示操作的表達詞典:可以添加
var mappings = new Dictionary<string, Expression<Func<int, int, bool>>>()
{
{">", (Expression<Func<int, int, bool>>)((a,b)=> a > b)},
{"<", (Expression<Func<int, int, bool>>)((a,b)=> a < b)},
{"==", (Expression<Func<int, int, bool>>)((a,b)=> a == b)},
};
等操作。
還有一個幫助器方法,我們將用它在整個表達式中用一個表達式替換另一個表達式的所有實例。
它使用該訪問者:
public class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
而只是把它包裝在更清晰的語法:
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
從那裏,我們繼續前進的問題的肉,創建過濾器的操作一個給定的查詢,其中兩個給定的操作數使用給定的操作符進行評估。它將查詢過濾,每個操作數的選擇器,然後操作。然後它用操作數選擇器替換操作參數的所有實例,並用左邊的選擇器的參數替換正確的選擇器參數,以便在最終產品中有一個實際參數,然後將其包裝到lambda中並通過到Where
:
public static IQueryable<TIn> WhereOperator<TIn, TLeft, TRight>(
this IQueryable<TIn> query,
Expression<Func<TIn, TLeft>> leftSelector,
Expression<Func<TIn, TRight>> rightSelector,
Expression<Func<TLeft, TRight, bool>> operation)
{
var newRightBody = rightSelector.Body.Replace(rightSelector.Parameters[0],
leftSelector.Parameters[0]);
var newOperator = operation.Body.Replace(operation.Parameters[0], leftSelector.Body)
.Replace(operation.Parameters[1], newRightBody);
var lambda = Expression.Lambda<Func<TIn, bool>>(newOperator,
leftSelector.Parameters[0]);
return query.Where(lambda);
}
用法示例:
IQueryable<Tuple<int, int>> query = new[] { Tuple.Create(1, 2) }
.AsQueryable();
var query2 = query.WhereOperator(pair => pair.Item1, pair => pair.Item2
, mappings[">"]);
在我們使用的內存queryables這種情況下,但作爲query2.Expression
會告訴你,這其實看起來與已經叫:
var query3 = query.Where(pair => pair.Item1 > pair.Item2);
在查詢語法中使用LINQ時,您可以使用[let子句](http://msdn.microsoft.com/zh-cn/library/vstudio/bb383976.aspx)來評估和存儲某些值以供以後使用查詢。 – pasty
這裏使用'Select(m => m)'是什麼意思? – dasblinkenlight
我認爲Select是需要的,即使它是爲所有人設計的,只是我自己學到的方式全是 – PRX