过滤器的动态表达式IQueryable

本文关键字:IQueryable 表达式 动态 过滤器 | 更新日期: 2023-09-27 18:15:21

我有一种情况,我只有属性名称(字符串)和期望过滤的值。如果有任何名称重复,我需要过滤列表以返回true

记住过滤器应该自己排除它。表达式为:p => p.Id != currentId

<标题> 代码

由于属性是字符串,我决定创建一个动态表达式来解决这个问题。

[TestMethod]
public void TestingExpression()
{
    // Arrange
    var fix = new Fixture();
    var list = fix.Build<User>()
                    .With(p => p.Name)
                    .OmitAutoProperties()
                    .CreateMany(20).AsQueryable(); // Create IQueryable<User> with 20 users
    // Act 
    var currentId = 2;
    var uniquePropName = "Name";
    var uniqueValue = "{NotFoundValue}";
    // Expression: p => p.Id != currentId
    ParameterExpression pId = Expression.Parameter(typeof(int), "Id");
    ConstantExpression cId = Expression.Constant(currentId, typeof(int));
    BinaryExpression notCurrent = Expression.NotEqual(pId, cId);
    Expression<Func<int, bool>> NotCurrentExpr =
        Expression.Lambda<Func<int, bool>>(
            notCurrent,
            new ParameterExpression[] { pId });
    // Expression: p.{uniquePropName} == {uniqueValue}
    ParameterExpression pUnique = Expression.Parameter(typeof(string), uniquePropName);
    ConstantExpression cUnique = Expression.Constant(uniqueValue, typeof(string));
    BinaryExpression checkUnique = Expression.Equal(pUnique, cUnique);
    Expression<Func<string, bool>> CheckUniqueExp =
        Expression.Lambda<Func<string, bool>>(
            checkUnique,
            new ParameterExpression[] { pUnique });

    var exp = Expression.And(NotCurrentExpr, CheckUniqueExp);
    // Asset
    list.Provider.CreateQuery<User>(exp).ToList()
            .Should().HaveCount(19);
}

目标是创建一个动态表达式:query.Any(p => p.Id != id && p.{Dynamic} == nome);

但我不知道如何继续…

谢谢

过滤器的动态表达式IQueryable

可以在这里找到一个很好的教程。

你似乎把参数和属性搞混了。下面是一个进一步的例子:

//user => user.SomeProperty == someValue
//the parameter of the predicate, a User object in your case 
ParameterExpression parameter = Expression.Parameter(typeof(User), "user");
//the property of the user object to use in expression
Expression property = Expression.Property(parameter, myPropertyNameString);
//the value to compare to the user property
Expression val = Expression.Constant(myValueToCompare);
//the binary expression using the above expressions
BinaryExpression expEquals = Expression.Equal(property, val);
//create the Expression<Func<T, Boolean>>
var predicate = Expression.Lambda<Func<User, Boolean>>(expEquals, parameter);

此外,在你的代码中,你尝试创建两个lambdas,而你的目标是生成

p => p.Id != id && p.{Dynamic} == nome

这是一个单独的lambda,它接受一个参数,主体由两个二进制表达式和一个产生Boolean结果的条件AND运算符组成。您应该使用Expression.AndAlso()&&运算符应用于二进制表达式,然后使用Expression.Lambda<Func<User, Boolean>>()获得最终的lambda表达式。