问题描述
遇到了一个问题,我需要动态地板条linq表达式.但是我似乎无法缠绕着它.
所以首先我得到了一个检查列表框.如果我从选择的文件中输入值,则在运行代码之前,我将不知道会有多少个参数.然后,计划是根据复选框中元素的名称构造LINQ句子.让我说明: 我想创建一个看起来像这样的LINQ语句:
var result = from n in data where n.Item1 == "someValueFromCheckBox" select n;
数据,数据是:
List<Tuple<string, string>>
,只要用户仅从复选框中选择一个项目,就可以了.但是例如,当用户选择两个项目时,我需要创建一个看起来像这样的Linqu表达式:
var result = from n in data where n.Item1 == "someValueFromCheckBox" || n.Item1 == "someValueFromCheckBox1" select n;
所以我的第一个想法是将LINQ语句构建为字符串.以以下方式:
var selectedItems = checkedListBoxSelectedTerms.CheckedItems; var linqStatement = ""; for (int i = 0; i < selectedItems.Count; i++ ) { linqStatement += selectedItems[i].ToString() + "|| n.item1 ==" ; } //this is simply to remove the || "n.Item1 ==", at the end because it is not needed after the last selecteditem. linqStatement = linqStatement.Remove(linqStatement.Length - 13, 13);
但这没有按计划工作,因为当我这样放入时:
var result = from n in data where n.Item1 == linqStatement select n;
整个过程变成了字符串.而且我不能让" n.item1 =="成为字符串.从理论上讲,解决方案对我的使用非常有用,因为我不必担心复选框中的manay元素以及用户选择多少元素,但是我不能将整个元素整体作为字符串传递.因此,任何帮助都会被阐明,因为我似乎找不到一个很好的例子来做这样的事情.
预先感谢!
推荐答案
对于这样一个简单的示例,您应该简单地拥有列表或 set 字符串,然后做Contains.例如
var selectedItems = checkedListBoxSelectedTerms.CheckedItems .Select(x => x.ToString()).ToList(); var result = from n in data where selectedItems.Contains(n.Item1) select n;
如果您需要更灵活的动态构建功能,请尝试 dynamic linq 或 pedicateBuilder .
其他推荐答案
PredicateBuilder是我用于动态查询的方法.
请参阅此处以获取更多信息:
http://www.albahari.com/nuthari.com/nutshell/nutshell/nutshell/predicatebuilder.aspx /p>
其他推荐答案
因此,您要寻找的是可以将任何数量表达式和或或它们一起使用的谓词建筑商的实现.这是将与任何查询提供商合作的实施:
public static class PredicateBuilder { 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>> expr1, Expression<Func<T, bool>> expr2) { var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]); return Expression.Lambda<Func<T, bool>> (Expression.OrElse(expr1.Body, secondBody), expr1.Parameters); } public static Expression<Func<T, bool>> And<T>( this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]); return Expression.Lambda<Func<T, bool>> (Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters); } }
使用:
internal 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); }
这使您可以采用任何两个表达式并创建一个新表达式,这是将它们共同作用的结果.
List<Tuple<string, string>> list = CreateList(); var finalExpression = list.Aggregate(PredicateBuilder.False<Data>(), (predicate, pair) => predicate.Or(n => n.Item1 == pair.Item2)); var query = data.Where(finalExpression);
问题描述
Got an problem where I need to crate an linq expression dynamically. But I cant seem to wrap my head around it.
So first off I got an check list box. Where I input values from a file that is selected, hence I will not know how many parameters there will be there before I run the code. Then the plan is to construct a linq sentence based on the name of the elements in the checkbox. Let me illustrate: I want to create an linq statement that looks like this:
var result = from n in data where n.Item1 == "someValueFromCheckBox" select n;
Where the data, is an tupled list like :
List<Tuple<string, string>>
And that is fine as long as the user only selects one item from the checkbox. But when the user for example selects two items, I need to create a linqu expression that looks like this:
var result = from n in data where n.Item1 == "someValueFromCheckBox" || n.Item1 == "someValueFromCheckBox1" select n;
So my first thought was to build the linq statement as a string. In the following manner:
var selectedItems = checkedListBoxSelectedTerms.CheckedItems; var linqStatement = ""; for (int i = 0; i < selectedItems.Count; i++ ) { linqStatement += selectedItems[i].ToString() + "|| n.item1 ==" ; } //this is simply to remove the || "n.Item1 ==", at the end because it is not needed after the last selecteditem. linqStatement = linqStatement.Remove(linqStatement.Length - 13, 13);
But that did not work as planned, because when I put it in like this:
var result = from n in data where n.Item1 == linqStatement select n;
The whole thing becomes a string. And I cant have the "n.Item1 ==" to be a string. In theory that solution would work great for my use, because I would not have to worry about how manay elements that are in the checkbox and how many elements the user selects, but I cannot pass linqStatement whole as a string. So any help would be appriciated, because I cant seem to find an good example to do something like this.
Thanks in advance!
推荐答案
For such a simple example, you should simply have a list or set of strings, and then do Contains. E.g.
var selectedItems = checkedListBoxSelectedTerms.CheckedItems .Select(x => x.ToString()).ToList(); var result = from n in data where selectedItems.Contains(n.Item1) select n;
If you need more flexible dynamic building capabilities, try something like Dynamic LINQ or PredicateBuilder.
其他推荐答案
The PredicateBuilder is what I use for dynamic queries.
Please see here for more info:
http://www.albahari.com/nutshell/predicatebuilder.aspx
其他推荐答案
So what you're looking for is an implementation of a predicate builder that can take any number of expressions and OR them together. Here is an implementation that will work with any query provider:
public static class PredicateBuilder { 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>> expr1, Expression<Func<T, bool>> expr2) { var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]); return Expression.Lambda<Func<T, bool>> (Expression.OrElse(expr1.Body, secondBody), expr1.Parameters); } public static Expression<Func<T, bool>> And<T>( this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]); return Expression.Lambda<Func<T, bool>> (Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters); } }
which uses:
internal 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); }
This allows you to take any two expressions and create a new expression that is the result of ORing them together.
List<Tuple<string, string>> list = CreateList(); var finalExpression = list.Aggregate(PredicateBuilder.False<Data>(), (predicate, pair) => predicate.Or(n => n.Item1 == pair.Item2)); var query = data.Where(finalExpression);