【问题标题】:Dynamic expression for filter IQueryable过滤器 IQueryable 的动态表达式
【发布时间】:2013-05-27 00:51:37
【问题描述】:

我有一种情况,我只有属性名称(字符串)和欲望过滤器的值。 如果重复任何名称,我需要过滤列表以返回 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 =&gt; p.Id != id &amp;&amp; p.{Dynamic} == nome);

但我不知道如何继续..

谢谢

【问题讨论】:

  • 可能的相同问题:stackoverflow.com/questions/1689199/…
  • @BryanHong 不是同一个问题!如您所见,我的代码不使用反射。另一个细节是我的疑问是如何在我的 IQueryable 中应用表达式。问题相似,但不一样。

标签: c# linq lambda linq-expressions


【解决方案1】:

可以在here找到一个不错的教程。

您似乎混淆了参数和属性。再举一个例子:

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

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

p =&gt; p.Id != id &amp;&amp; p.{Dynamic} == nome

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

【讨论】:

  • 抱歉耽搁了:我有一个错误> System.ArgumentException:'System.Func2[CreditoImobiliarioBB.Model.Modalidade,System.Int32]' cannot be used for return type 'System.Int32' in Expression> lambdaExpr = Expression.Lambda>( PropertyId);`我的表达是private readonly Expression&lt;Func&lt;T, int&gt;&gt; PropertyId;
  • 看到这个:fluentvalidation.codeplex.com/discussions/353331#post1050039 在行var currentId = Expression.Lambda&lt;Func&lt;int&gt;&gt;(PropertyId).Compile()(); // Get Current ID 我得到了错误。 System.ArgumentException: Expression of type 'System.Func2[CreditoImobiliarioBB.Model.Modalidade,System.Int32]' 不能用于返回类型'System.Int32'`
  • @Ridermansb,添加了更多细节。看看我链接的教程,你想做的和它很相似。
  • 是的,我读过这篇文章。我承认,我不是 lambdas 专家 :) 我想你已经回答了这个问题。问题是我无法检索通过.MustBeUnique(p =&gt; p.Id, repositorio);(Id 值)传递给函数的值,因此无法测试表达式。请参阅full error here 在我的课堂上,我有private readonly Expression&lt;Func&lt;T, int&gt;&gt; PropertyId; 属性。需要获取此表达式的 int 值。
猜你喜欢
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
  • 2021-01-15
  • 2021-01-04
  • 1970-01-01
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多