4

I use a dynamic filter, that filters a collection using object properties, operators and values. Now, if the property is a string, the operator is "contains" and the value is "word", the filtered objects containing the "world" should be filtered accordingly.

In Linq I have the Expression.Equal, NotEqual, GreaterThanOrEqual, LessThanOrEqual

but don't have "Contains". How to replace it?

Consider the following code (in VB.NET, but does not matter)

  Select Case compOp
    Case ComparisonOperator.Contains
      ' ?????? WHAT HERE ???? '
      filterExpression = Expression.Lambda(Of Func(Of PropertyType, Boolean))(Expression.Equal(myObjPropertyParam, myConstExpression), myObjParam)

    Case ComparisonOperator.Different
      filterExpression = Expression.Lambda(Of Func(Of PropertyType, Boolean))(Expression.NotEqual(myObjPropertyParam, myConstExpression), myObjParam)

    Case ComparisonOperator.Equal
      filterExpression = Expression.Lambda(Of Func(Of PropertyType, Boolean))(Expression.Equal(myObjPropertyParam, myConstExpression), myObjParam)

    Case ComparisonOperator.GreatherThanOrEqual
      filterExpression = Expression.Lambda(Of Func(Of PropertyType, Boolean))(Expression.GreaterThanOrEqual(myObjPropertyParam, myConstExpression), myObjParam)

    Case ComparisonOperator.LessThanOrEqual
      filterExpression = Expression.Lambda(Of Func(Of PropertyType, Boolean))(Expression.LessThanOrEqual(myObjPropertyParam, myConstExpression), myObjParam)
  End Select

EDIT:

Used Solution, gratie to Thomas Levesque and Jon Skeet )

  Dim expr As Expression = Nothing

  Select Case compOp
    Case ComparisonOperator.Contains
      expr = Expression.Call(myObjPropertyParam, "Contains", Nothing, constantExpression)
    Case ComparisonOperator.Different
      expr = Expression.NotEqual(myObjPropertyParam, constantExpression)
    Case ComparisonOperator.Equal
      expr = Expression.Equal(myObjPropertyParam, constantExpression)
    Case ComparisonOperator.GreatherThanOrEqual
      expr = Expression.GreaterThanOrEqual(myObjPropertyParam, constantExpression)
    Case ComparisonOperator.LessThanOrEqual
      expr = Expression.LessThanOrEqual(myObjPropertyParam, constantExpression)
  End Select

  filterExpression = Expression.Lambda(Of Func(Of PropertyType, Boolean))(expr, myObjParam)
serhio
  • 28,010
  • 62
  • 221
  • 374

1 Answers1

3

There is no Contains operator (although there are methods named Contains). It would only make sense for some types (like String, collections and a few others), but not for others; for instance how would you define the Contains operator for integers or dates ?

Now, if you want to apply the Contains method to a string via a lambda expression, you have to generate an expression that calls the method, using Expression.Call.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • effectivement... But I should build such expressions however, at least for string peroperties – serhio Aug 25 '11 at 18:01
  • 1
    @serhio: It's not clear what you mean - but it's not hard to use Expression.Call, and as it happens I gave an example of using it today: http://stackoverflow.com/questions/7193974/how-do-i-nest-a-call-to-a-method-within-a-call-to-a-method-using-expression-call/7194171#7194171 – Jon Skeet Aug 25 '11 at 18:02
  • @Jon: I use a dynamic filter, that filters a collection using object properties, operators and values. Now, if the property is a string, the operator is "contains" and the value is "word", the filtered objects containg the "world" should be filtered accordingly. I suppose, besides Call I should use something like Evaluate, in order to obtain a boolean value from the lambda expression – serhio Aug 25 '11 at 18:07
  • 1
    @serhio: Well you'll still need Expression.Lambda, but just with Expression.Call. By the way, as each case of your select uses Expression.Lambda, why not pull that into a single call afterwards? Make the Select just work out the expression that needs to be used with Expression.Lambda. – Jon Skeet Aug 25 '11 at 18:14
  • @Jon: This select builds a single expression. I have a grid, where each row is an expression. That expressions are combined with OR or AND. So, that expression is returned to an other function that combines them into a final expression... that is finally applied to a collection. – serhio Aug 25 '11 at 18:20
  • @serhio: I don't understand how that relates to my previous comment. Have a separate local variable which is assigned in the Select/Case, and then set `filterExpression` using `Expression.Lambda` after the Select/Case. – Jon Skeet Aug 25 '11 at 18:22
  • I added a solution according to your suggestions. Thanks a lot! – serhio Aug 25 '11 at 18:34
  • Thomas, @jon-skeet: what about NotContains()? Can I invert the Contains result? – serhio Aug 29 '11 at 15:17
  • 1
    @serhio, use `Expression.Not` around `Expression.Call` – Thomas Levesque Aug 29 '11 at 15:23