Reputation: 1586
I am stuck on this for hours. All I want to do is build an Expression tree by rewriting this following expression using Expression class APIs:
var Expression<Func<T, bool>> expr = x => x.SomeProperty == value;
What I got so far are:
{
var param = Expression.Parameter(typeof(T), "x");
var lhs = Expression.Property(param, "SomeProperty");
var rhs = Expression.Constant(value, value.GetType());
return Expression.Call(typeof(object).GetMethod("Equals", BindingFlags.Static | BindingFlags.Public), lhs, rhs);
}
This works fine if T
is a primitive type or enumeration. But I got an exception if T is a reference type, a class
etc.
Exception Message:
Unable to create a constant value of type '
TypeName
'. Only primitive types or enumeration types are supported in this context.
Thanks in advance.
Upvotes: 3
Views: 632
Reputation: 1586
The expression generated was passed to a Linq Where
call. Like this.
Context.Sources.Where(criteria.BuildQuery());
The exception was thrown when the expression is being evaluated/translated.
If I compile the expression and then pass a delegate to the Where
call, everything works as expected.
Context.Sources.Where(criteria.BuildQuery().Compile());
I am not sure what difference it makes, if someone knows why please enlighten us.
Upvotes: 0
Reputation: 935
You don't need to specify the type explicitly, in this case, as long as the value is not null (which I'm assuming it isn't, as you're calling GetType()
on it).
This should do it.
var param = Expression.Parameter(typeof(T), "x");
var property = Expression.Property(param, "SomeProperty");
var compareValue = Expression.Constant(value);
var equals = Expression.Equal(property, compareValue);
return Expression.Lambda<Func<T, bool>>(equals, param);
Upvotes: 1