C# 从对象生成表达式时为lambda声明提供的参数数量不正确

C# 从对象生成表达式时为lambda声明提供的参数数量不正确,c#,.net,lambda,expression,C#,.net,Lambda,Expression,我创建了一个将对象转换为表达式的方法 private Expression<Func<TDto, bool>> GetObjectAsExpression<TSearchDto, TDto>(TSearchDto searchDto) where TSearchDto : class where TDto : class { List<ParameterExpression> parameterExpressions = new L

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

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

我还搜索了一个nuget包或可以实现这一点和更多功能的源代码。请建议一个解决方案或一个现有的包来实现这一点和更多功能。

不确定您对整个
节点计数的意图是什么,但这就是问题所在。您正在生成的
Func
只有一个参数-一个
TDto
进入,一个
bool
出来-因此您不应该将整个参数列表传递给您构建的谓词

此外,为了简洁起见,如果您以
true
开始谓词,则不需要空检查-您只需将
s链接起来即可

两者兼而有之:

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
    );
}
私有表达式GetObjectAsExpression(TSearchDto searchDto)
where-TSearchDto:class其中TDto:class
{
ParameterExpression singleParameterExpression=Expression.Parameter(typeof(TDto),“node”);
Expression-predicateBody=Expression.Constant(true);
foreach(searchDto.GetType().GetProperties中的PropertyInfo属性(BindingFlags.Public | BindingFlags.Instance))
{
表达式left=Expression.Property(singleParameterExpression,Property.Name);
Expression=Expression.Equal(左,Expression.Constant(property.GetValue(searchDto));
predicateBody=Expression.And(predicateBody,Expression);
}
返回表达式.Lambda(
谓词库,
单参数表达式
);
}

我想这会得到你想要的结果。

就这么简单,这消耗了我的工作时间。我正在尝试构建通用存储库和通用uow,它适用于所有域模型。还涉及在运行时将DTO映射到实体。这就是我的雇主想要的。他相信,通过建造这两件作品,他可以节省大量的时间和工作。
GetObjectAsExpression<object, TDto>(new { CaseNumber = "00100283900813414832", WareHouse = "008" })
System.ArgumentException: 'Incorrect number of parameters supplied for lambda declaration'
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
    );
}