I am trying to create an expression of the following form:
e => e.CreationDate;
CreationDate is of type
long, however I want the expression to return an
I want to use
object as a return type because the expression is built dynamically at runtime based on a query paramater. The query parameter specifies the property to access in the expression, such as:
> entities?order=creationDate > entities?order=score
As you can see, I can order by different properties with different types, so a return type
object would allow me to build the expression as generic as possible.
The problem is that when I try to create the expression:
ParameterExpression entityParameter = Expression.Parameter(typeof(Entity), "e"); Expression propertyAccess = Expression.Property(entityParameter, property); Expression<Func<Entity, object>> result = Expression.Lambda<Func<Entity, object>>(propertyAccess, entityParameter);
I get the following exception:
Expression of type 'System.Int64' cannot be used for return type 'System.Object'
It is strange, because as far as I know, all types extend from
object (It seems polymorphism is not yet supported by expression trees).
Nevertheless, I searched on the web and stumbled with this similar question:
Following Jon Skeet's answer, I modified my last line to:
Expression<Func<Entity, object>> result = Expression.Lambda<Func<Entity, object>>(Expression.Convert(propertyAccess, typeof(object)), entityParameter);
This works fine, but it doesn't generate the expression I want. Instead, it generates something like this:
e => Convert(e.CreationDate)
I cannot use this solution, because later in the program an exception is thrown if the expression body is not a
MemberExpression (i.e., a member access operation)
I kept searching on the Internet for a satisfying answer, but couldn't find any.
How can I achieve
e => e.CreationDate where return type is
Depending on how you use
result you could create it dynamically with the delegate type
Func<Entity, long> and type it as a
ParameterExpression entityParameter = Expression.Parameter(typeof(Entity), "e"); Expression propertyAccess = Expression.Property(entityParameter, property); var funcType = typeof(Func<,>).MakeGenericType(typeof(Entity), property.PropertyType); LambdaExpression result = Expression.Lambda(funcType, propertyAccess, entityParameter);
Short answer: no, it is not possible. Value types need to be boxed to be seen as objects. The compiler does it for you normally, but if you build code yourself (e.g expression trees), you need to specify it as an explicit conversion, the way you see it in the found answer. If you cannot have it as a non-generic LambdaExpression, I would handle the convert case additionally where you expect the MemberExpression, or use PropertyInfo, and construct the orderby Expression only in the last moment.