【问题标题】:Add variable amount of conditions to expression in loop C#在循环C#中向表达式添加可变数量的条件
【发布时间】:2021-06-29 21:24:18
【问题描述】:
var row = parser.ReadFields();
Expression<Func<DataRow, bool>> expression = null;
foreach (var pairToCheck in mappingDictionary)
{
    Expression<Func<DataRow, bool>> newCondition = r => r[pairToCheck.Value].ToString() == row[pairToCheck.Key];
    if (expression == null)
        expression = newCondition;
    else
        expression = Expression.And(expression, newCondition.Body); // Compile error, I can't do this apparently
}

var recordFound = dt.AsEnumerable().Where(expression.Compile()).Count() > 0;

请参见上面的代码,我试图在 DataTable (var dt) 中查找记录,但该记录必须满足的条件数量是可变的。我尝试使用 Expression.And 添加条件,但它会将表达式转换为 BinaryExpression 类型,我无法再将其转换回原来的 Expression>。我在这里想念什么?我的方法至少是正确的吗?

【问题讨论】:

    标签: c#


    【解决方案1】:

    您需要进行一些更复杂的处理。像这样的:

    Expression expression = null;
    var parameter = Expression.Parameter(typeof(DataRow)); // create a parameter for your future lambda
    foreach (var pairToCheck in mappingDictionary)
    { 
       Expression<Func<DataRow, bool>> newCondition = r => r[pairToCheck.Value].ToString() == row[pairToCheck.Key];
       // build new body replacing parameter to correct one
       var newBody = newCondition.Body.ReplaceParameter(newCondition.Parameters.First(), parameter); 
    
       if (expression == null) 
           expression = newBody; 
       else 
           expression = Expression.AndAlso(expression, newBody); // use AndAlso, And is a bitwise AND operation
    }
    
    var result = Expression.Lambda<Func<DataRow, bool>>(expression, parameter); // construct lambda
    var recordFound = dt.AsEnumerable().Where(result.Compile()).Count() > 0;
    

    然后ReplaceParameter 方法就出现了:

    public static class ExpressionExt
    {
        public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
        {
            return new ParameterReplacingVisitor { Source = source, Target = target }.Visit(expression);
        }
    
        class ParameterReplacingVisitor : ExpressionVisitor
        {
            public ParameterExpression Source;
            public Expression Target;
            protected override Expression VisitParameter(ParameterExpression node)
            {
                return node == Source ? Target : base.VisitParameter(node);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-30
      • 2014-04-13
      • 1970-01-01
      • 1970-01-01
      • 2011-10-04
      • 2020-09-26
      • 2019-07-11
      • 1970-01-01
      相关资源
      最近更新 更多