运行时 Lambda 表达式中的多个条件 C#
我想知道如何通过输入多个参数来制作一棵表达式树
示例:
dataContext.Users.Where(u => u.username == "Username" && u.password == "Password")
目前我所做的代码如下,但希望就条件是 OR 还是 AND 做出更一般的说明
public Func<TLinqEntity, bool> ANDOnlyParams(string[] paramNames, object[] values)
{
List<ParameterExpression> paramList = new List<ParameterExpression>();
foreach (string param in paramNames)
{
paramList.Add(Expression.Parameter(typeof(TLinqEntity), param));
}
List<LambdaExpression> lexList = new List<LambdaExpression>();
for (int i = 0; i < paramNames.Length; i++)
{
if (i == 0)
{
Expression bodyInner = Expression.Equal(
Expression.Property(
paramList[i], paramNames[i]),
Expression.Constant(values[i]));
lexList.Add(Expression.Lambda(bodyInner, paramList[i]));
}
else
{
Expression bodyOuter = Expression.And(
Expression.Equal(
Expression.Property(
paramList[i], paramNames[i]),
Expression.Constant(values[i])),
Expression.Invoke(lexList[i - 1], paramList[i]));
lexList.Add(Expression.Lambda(bodyOuter, paramList[i]));
}
}
return ((Expression<Func<TLinqEntity, bool>>)lexList[lexList.Count - 1]).Compile();
}
谢谢
I would like to know how to be able to make an Expression tree by inputting more than one parameter
Example:
dataContext.Users.Where(u => u.username == "Username" && u.password == "Password")
At the moment the code that I did was the following but would like to make more general in regards whether the condition is OR or AND
public Func<TLinqEntity, bool> ANDOnlyParams(string[] paramNames, object[] values)
{
List<ParameterExpression> paramList = new List<ParameterExpression>();
foreach (string param in paramNames)
{
paramList.Add(Expression.Parameter(typeof(TLinqEntity), param));
}
List<LambdaExpression> lexList = new List<LambdaExpression>();
for (int i = 0; i < paramNames.Length; i++)
{
if (i == 0)
{
Expression bodyInner = Expression.Equal(
Expression.Property(
paramList[i], paramNames[i]),
Expression.Constant(values[i]));
lexList.Add(Expression.Lambda(bodyInner, paramList[i]));
}
else
{
Expression bodyOuter = Expression.And(
Expression.Equal(
Expression.Property(
paramList[i], paramNames[i]),
Expression.Constant(values[i])),
Expression.Invoke(lexList[i - 1], paramList[i]));
lexList.Add(Expression.Lambda(bodyOuter, paramList[i]));
}
}
return ((Expression<Func<TLinqEntity, bool>>)lexList[lexList.Count - 1]).Compile();
}
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Expression.And
在这里使用是错误的,它是按位与。您需要AndAlso
。除此之外,您似乎已经知道如何构建表达式树的机制。所以你真正要问的是如何让构建方法的调用者指定一种更复杂、更灵活的方式来组合不同的条件。
最终为了真正的灵活性,您需要一种迷你查询语言。解析语言以构建表达式树。
在短期内,您可能会使用更简单的东西:原始表达式列表和 bool 标志来说明它们是否应该与 && 结合使用。或||。
更新 - 我注意到您实际上正在将结果表达式编译为真正的委托。这让我想知道为什么你一开始要这么艰难地做这件事。为什么不像您最初的示例那样将表达式写为 lambda? (如果您使用的是 Linq to SQL 或 EF,则无论如何都不应该编译表达式。)
更新 2 - 您可能需要的是 动态 Linq。
Expression.And
is the wrong thing to use here, it's the bitwise and. You wantAndAlso
.It seems like you aside from that you already know the mechanics of how to build the expression tree. So what you're really asking is how can you let the caller of your building-method specify a more complicated, flexible way of combining different conditions.
Ultimately for true flexibility you need a mini query language. Parse the language to build the expression tree.
In the short term, you might get by with something much simpler: a list of primitive expressions and a bool flag to say whether they should be combined with && or ||.
Update - I notice you're actually compiling the resulting expression into a real delegate. This makes me wonder why you're doing this the hard way in the first place. Why not just write the expression as a lambda, as in your initial example? (If you're using Linq to SQL or EF, you shouldn't be compiling the expression anyway.)
Update 2 - What you probably need is Dynamic Linq.