合并表达式以使用相同的 Lambda 参数。

huangapple go评论62阅读模式
英文:

merge expressions to use the same lambda parameter

问题

有一个 Expression<Func<T, string>> 数组和一个 string str

它可能有这样的值:
{ m => m.FirstName, m => m.LastName}

我想生成一个 Lambda 表达式,像这样:

m => m.FirstName.Contains(str) || m.LastName.Contains(str)

问题在于,当有多于 1 个表达式时,每个表达式都有它自己的 lambda 参数 (m =>)。

所以当我调用:

Expression.Lambda<Func<T, bool>>(OrExpr, 这里需要只有一个 lambda 参数

(目前我知道的唯一解决办法是生成一个新的 Expression.Parameter 和新的 Expression.MakeMemberAccess[],使用我的新参数)

英文:

having an array of Expression<Func<T, string>> and a string str

which could have a value like this:
{ m => m.FirstName, m => m.LastName}

I wanted to generate a Lambda expression that does this:

m => m.FirstName.Contains(str) || m.LastName.Contains(str)

The problem is that when there's more than 1 Expression, each has its lambda parameter (m =>)

so when I call:

Expression.Lambda<Func<T, bool>>(OrExpr, here needs to be just one lambda parameter

(for now the only solution I know is to generate a new Expression.Parameter and new Expression.MakeMemberAccess[] using my new parameter)

答案1

得分: 0

给定propFns作为Expression<Func<T, string>>数组和string str,您可以执行以下操作:

var ansParam = propFns[0].Parameters[0];
var newBody = propFns.Select(f => (Expression)Expression.Call(
                                        ReplacingExpressionVisitor.Replace(f.Parameters[0], ansParam, f.Body),
                                        typeof(String).GetMethod("Contains", new[] { typeof(String) }),
                                        Expression.Constant(str))
              ).Aggregate(Expression.OrElse);
var newLambda = Expression.Lambda<Func<TestClass,bool>>(newBody, ansParam);

注意:如果您没有使用EF Core,并且没有可用的ReplacingExpressionVisitor,您可以使用自己的版本:

/// <summary>
/// 用另一个Expression替换Expression(引用Equals)。
/// </summary>
/// <param name="orig">原始Expression。</param>
/// <param name="from">从Expression。</param>
/// <param name="to">替换为的Expression。</param>
/// <returns>Expression,其中所有from的出现都替换为to。</returns>
public static T Replace&lt;T&gt;(this T orig, Expression from, Expression to) where T : Expression =&gt; (T)new ReplaceVisitor(from, to).Visit(orig);

/// <summary>
/// ExpressionVisitor,用另一个Expression替换Expression(即Equals)。
/// </summary>
public class ReplaceVisitor : ExpressionVisitor {
    readonly Expression from;
    readonly Expression to;

    public ReplaceVisitor(Expression from, Expression to) {
        this.from = from;
        this.to = to;
    }

    public override Expression Visit(Expression node) =&gt; node == from ? to : base.Visit(node);
}
英文:

Given propFns as an array of Expression&lt;Func&lt;T, string&gt;&gt; and string str, you can do:

var ansParam = propFns[0].Parameters[0];
var newBody = propFns.Select(f =&gt; (Expression)Expression.Call(
                                        ReplacingExpressionVisitor.Replace(f.Parameters[0], ansParam, f.Body),
                                        typeof(String).GetMethod(&quot;Contains&quot;, new[] { typeof(String) }),
                                        Expression.Constant(str))
              ).Aggregate(Expression.OrElse);
var newLambda = Expression.Lambda&lt;Func&lt;TestClass,bool&gt;&gt;(newBody, ansParam);

NOTE: If you are not using EF Core, and don't have ReplacingExpressionVisitor available, you can use your own version:

/// &lt;summary&gt;
/// Replaces an Expression (reference Equals) with another Expression
/// &lt;/summary&gt;
/// &lt;param name=&quot;orig&quot;&gt;The original Expression.&lt;/param&gt;
/// &lt;param name=&quot;from&quot;&gt;The from Expression.&lt;/param&gt;
/// &lt;param name=&quot;to&quot;&gt;The to Expression.&lt;/param&gt;
/// &lt;returns&gt;Expression with all occurrences of from replaced with to&lt;/returns&gt;
public static T Replace&lt;T&gt;(this T orig, Expression from, Expression to) where T : Expression =&gt; (T)new ReplaceVisitor(from, to).Visit(orig);

/// &lt;summary&gt;
/// ExpressionVisitor to replace an Expression (that is Equals) with another Expression.
/// &lt;/summary&gt;
public class ReplaceVisitor : ExpressionVisitor {
    readonly Expression from;
    readonly Expression to;

    public ReplaceVisitor(Expression from, Expression to) {
        this.from = from;
        this.to = to;
    }

    public override Expression Visit(Expression node) =&gt; node == from ? to : base.Visit(node);
}

huangapple
  • 本文由 发表于 2023年2月27日 03:42:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75574587.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定