你可以這樣說:
class Program
{
public enum Operator
{
And,
Or
}
public class Condition
{
public Operator Operator { get; set; }
public string FieldName { get; set; }
public object Value { get; set; }
}
public class DatabaseRow
{
public int A { get; set; }
public string B { get; set; }
}
static void Main(string[] args)
{
var conditions = new List<Condition>
{
new Condition { Operator = Operator.And, FieldName = "A", Value = 1 },
new Condition { Operator = Operator.And, FieldName = "B", Value = "Asger" },
new Condition { Operator = Operator.Or, FieldName = "A", Value = 2 },
};
var parameter = Expression.Parameter(typeof (DatabaseRow), "x");
var currentExpr = MakeExpression(conditions.First(), parameter);
foreach (var condition in conditions.Skip(1))
{
var nextExpr = MakeExpression(condition, parameter);
switch (condition.Operator)
{
case Operator.And:
currentExpr = Expression.And(currentExpr, nextExpr);
break;
case Operator.Or:
currentExpr = Expression.Or(currentExpr, nextExpr);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
var predicate = Expression.Lambda<Func<DatabaseRow, bool>>(currentExpr, parameter).Compile();
var input = new[]
{
new DatabaseRow {A = 1, B = "Asger"},
new DatabaseRow {A = 2, B = "Hans"},
new DatabaseRow {A = 3, B = "Grethe"}
};
var results = input.Where(predicate).ToList();
}
static BinaryExpression MakeExpression(Condition condition, ParameterExpression parameter)
{
return Expression.Equal(
Expression.MakeMemberAccess(parameter, typeof (DatabaseRow).GetMember(condition.FieldName)[0]),
Expression.Constant(condition.Value));
}
}
這裏假設你有一個類作爲數據庫行與正確類型的模型。然後,您可以通過正則表達式將您的條件解析爲上面顯示的類型條件列表,並且提供的代碼可以將其轉換爲表達式樹。得到的表達式可以被編譯並運行(如圖所示)或轉換爲SQL(而不是將謂詞填充到IQueryable.Where中)。
你想查詢一個數據庫(使用類似LINQ to SQL的東西)還是內存列表? – svick 2013-02-12 15:53:27
數據庫,最好。如果容易,我可以將負載放入內存並在其中工作,但我寧願不要因爲數據庫相當龐大。 – anaximander 2013-02-13 09:01:22