53

I was trying to generate a simple Lambda Expression at runtime with no luck... something like this:

var result = queryableData.Where(item => item.Name == "Soap")

Here is my example class and a fixture queryable:

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
}

IQueryable<Item> queryableData = ...;

Then I generate a lambda expression at runtime correct code follows:

//"item" in "item =>..."
var item = Expression
    .Parameter(typeof(Item), "item");

//property of my item, this is "item.Name"
var prop = Expression
    .Property(item, "Name");

//then "Soap" in '... => item.Name=="Soap"'
var value = Expression.Constant("Soap");

//equality expression "==" in my primer
var equals = Expression.Equal(prop, value);

//then lambda
var lambda = Expression.Lambda<Func<Item, bool>>(equals, item);

//and here are the results    
var results = queryableData.Where(lambda);

Big thanks to dtb for advice!

CodeAddicted
  • 979
  • 2
  • 10
  • 13
  • Here is extended example with nested property: http://stackoverflow.com/questions/34270207/expression-lambda-and-query-generation-at-runtime-nested-property-where-examp – Piotr Czarnecki Dec 14 '15 at 15:32

1 Answers1

151

In the following query

var result = query.Where(item => item.Name == "Soap")

the lambda expression is

item => item.Name == "Soap"

You only need to construct this part, not the Where call which accepts an expression tree.

The expression tree for the lambda expression looks like this:

                     Lambda
                      /  \
                   Equal  Parameter
                   /   \    item
              Property  \
               "Name"   Constant
                 |       "Soap"
             Parameter         
               item

In code:

var item = Expression.Parameter(typeof(Item), "item");

var prop = Expression.Property(item, "Name");

var soap = Expression.Constant("Soap");

var equal = Expression.Equal(prop, soap);

var lambda = Expression.Lambda<Func<Item, bool>>(equal, item);

var result = queryableData.Where(lambda);
dtb
  • 213,145
  • 36
  • 401
  • 431
  • Sorry, but something is not clear enough. Here is a second expression: `var propId = Expression.Property(item, "Id"); var minId = Expression.Constant(15); var greaterThan = Expression.GreaterThan(propId, minId);` To combine **equal** and **greaterThan** with **&&** in lambda I need `var combined = Expression.AndAlso(equal, greaterThan);` Am I right? – CodeAddicted Nov 29 '11 at 19:05
  • @dtb I have object list with object in it like `{id = 1, year = "Year1", month = "Jan", val = 100, othval = 100}`, what I need is `{ id = 1 , Year1 = { Jan = { val = 100, othval = 100} }}`, where I don't know the `year` value and I don't know `month` also. Can this be achieved in `linq`? – Bharadwaj Feb 10 '15 at 06:25
  • I am not uderstanding why use the params ParameterExpression[]? "item" on: //then lambda var lambda = Expression.Lambda>(equals, item); do you have an exemple with more than one paramsw – Raphael Ribeiro Aug 02 '23 at 19:05