【问题标题】:Incorrect number of parameters supplied for lambda declaration while building expression from object从对象构建表达式时为 lambda 声明提供的参数数量不正确
【发布时间】:2019-08-13 09:25:09
【问题描述】:

我创建了一个将对象转换为表达式的方法。

private Expression<Func<TDto, bool>> GetObjectAsExpression<TSearchDto, TDto>(TSearchDto searchDto)
    where TSearchDto : class where TDto : class
{
    List<ParameterExpression> parameterExpressions = new List<ParameterExpression>();
    Expression predicateBody = default(Expression);
    int nodeCount = 1;
    foreach (PropertyInfo property in searchDto.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        ParameterExpression parameterExpression =
            Expression.Parameter(typeof(TDto), $"node{nodeCount++}");
        parameterExpressions.Add(parameterExpression);

        Expression left = Expression.Property(parameterExpression, property.Name);
        Expression expression = Expression.Equal(left, Expression.Constant(property.GetValue(searchDto)));
        if (predicateBody == null)
        {
            predicateBody = expression;
        }
        else
        {
            predicateBody = Expression.And(predicateBody, expression);
        }
    }

    return Expression.Lambda<Func<TDto, bool>>(
        predicateBody,
        parameterExpressions
    );
}

案例 1:当我使用单个属性调用此方法时,它工作正常。

GetObjectAsExpression<object, TDto>(new { CaseNumber = "00100283900813414832"})

案例 2:当我使用 2 个参数调用此方法时,它会引发错误

GetObjectAsExpression<object, TDto>(new { CaseNumber = "00100283900813414832", WareHouse = "008" })

有错误

System.ArgumentException: 'Incorrect number of parameters supplied for lambda declaration'

我还搜索了一个 nuget 包或可以完成此操作的源以及更多功能。请提出一个解决方案或一个现有的包来做这个等等。

【问题讨论】:

    标签: c# .net lambda expression


    【解决方案1】:

    不确定您对整个 nodeCount 的意图是什么,但这就是问题所在。您正在生成的Func 只有 一个 参数 - 单个 TDto 进入,bool 出来 - 所以你不应该通过您构建的谓词的完整参数列表。

    此外,为了简洁起见,如果您以 true 开头谓词,则不需要进行空值检查 - 您只需链接 Ands。

    两者兼顾:

    private Expression<Func<TDto, bool>> GetObjectAsExpression<TSearchDto, TDto>(TSearchDto searchDto)
        where TSearchDto : class where TDto : class
    {
        ParameterExpression singleParameterExpression = Expression.Parameter(typeof(TDto), "node");
    
        Expression predicateBody = Expression.Constant(true);
        foreach (PropertyInfo property in searchDto.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            Expression left = Expression.Property(singleParameterExpression, property.Name);
            Expression expression = Expression.Equal(left, Expression.Constant(property.GetValue(searchDto)));
            predicateBody = Expression.And(predicateBody, expression);
        }
    
        return Expression.Lambda<Func<TDto, bool>>(
            predicateBody,
            singleParameterExpression
        );
    }
    

    我认为它会给出你想要的结果。

    【讨论】:

    • 就这么简单,浪费了我的工作时间。
    • 尝试构建通用存储库和通用 uow,它适用于所有领域模型。并且还涉及在运行时将 Dtos 映射到实体。这就是我的雇主想要的。他相信他可以通过构建这两件作品来节省大量时间和工作量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多