gpt4 book ai didi

c# - 表达式树 : iterate through strings and check if they contained in another Expression

转载 作者:太空宇宙 更新时间:2023-11-03 21:17:26 26 4
gpt4 key购买 nike

我想要一个函数表达式> AnyColumnContains(string[] value)它遍历表的所有列并根据列检查值数组,仅当每个值都包含在任何列中时才返回 true。

我已经有一个函数可以将每一列与一个值进行匹配,但是我在扩展它以根据每个值检查列时遇到了问题

这是我得到的:

Expression<Func<T, bool>> AnyColumnContains<T>(string value){
var p = Expression.Parameter(typeof(T), "entity");

var fieldAccessors = typeof(T)
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(f => f.PropertyType == typeof(string))
.Select(f => Expression.Property(p, f))
.ToArray();

var fieldArray = Expression.NewArrayInit(typeof(string), fieldAccessors);

var concatCall = Expression.Call(typeof(string).GetMethod(
"Concat", new[] { typeof(string[]) }), fieldArray);

var contains = Expression.Call(
concatCall,
typeof(string).GetMethod("Contains", new[] { typeof(string) }),
Expression.Constant(value));

return Expression.Lambda<Func<T, bool>>(contains, p);
}

我尝试使用自己的扩展方法并将 Contains 替换为它,但问题是我使用 sqlite 并且无法转换表达式,因为提供者不知道这些方法

这就是我想要的:

Expression<Func<T, bool>> AnyColumnContains<T>(string[] values){
// ... //

var contains = // build Expression Tree that matches all values against concatCall and only returns true if all values are contained.

return Expression.Lambda<Func<T, bool>>(contains, 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);
}
}

它依赖于以下方法将一个表达式的所有实例替换为另一个表达式:

public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}

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);
}
}

现在我们所要做的就是为每个值调用单值版本的 AnyColumnContainsOr 所有结果:

public static Expression<Func<T, bool>> AnyColumnContains<T>(IEnumerable<string> values)
{
return values.Select(value => AnyColumnContains<T>(value))
.Aggregate((a, b) => a.Or(b));
}

关于c# - 表达式树 : iterate through strings and check if they contained in another Expression,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33082267/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com