Reputation: 31823
I am attempting to build a simple Where clause.
This is the code that does not work:
EDIT this code works fine now (thanks to answers below).
public class Item
{
public int Value { get; set; }
public string Name { get; set; }
}
var _List = new List<Item>
{
new Item{ Name = "Smith", Value = 1},
new Item{ Name = "Smith", Value = 2},
new Item{ Name = "Wesson", Value = 3},
new Item{ Name = "Wesson", Value = 4},
};
// Where(x => x.Value == 1)
var _Type = typeof(Item);
var _Prop = _Type.GetProperty("Value");
var _Param = Expression.Parameter(_Type, _Prop.Name);
var _Left = Expression.PropertyOrField(_Param, _Prop.Name);
var _Right = Expression.Constant(1, _Prop.PropertyType);
var _Body = Expression.Equal(_Left, _Right);
var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param);
var _Result = _List.AsQueryable().Where(_Where);
Thank you.
Upvotes: 4
Views: 4806
Reputation: 217323
There are several problems with your code:
You need to pass 1
and not "1"
for the integer constant 1
.
var _Right = Expression.Constant(1, _Prop.PropertyType);
Expression.Equals if two expression trees are equal. It returns a bool
.
Expression.Equal returns an expression tree that represents an equality check.
var _Body = Expression.Equal(_Left, _Right);
The parameter is of type Item
and not int
.
var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param);
The List<T> implements IEnumerable<T>, but not IQueryable<T>.
IEnumerable<T> works with delegates, while IQueryable<T> works with expression trees.
So you need to either compile your expression tree to a delegate
var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param).Compile();
var _Result = _List.Where(_Where);
or convert the list to IQueryable<T>.
var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param);
var _Result = _List.AsQueryable().Where(_Where);
Working code:
// Where(x => x.Value == 1)
var _Param = Expression.Parameter(typeof(Item), "x");
var _Left = Expression.PropertyOrField(_Param, "Value");
var _Right = Expression.Constant(1);
var _Body = Expression.Equal(_Left, _Right);
var _Where = Expression.Lambda<Func<Item, bool>>(_Body, _Param).Compile();
var _Result = _List.Where(_Where);
Upvotes: 5