Reputation: 5122
How to convert : Expression<Func<T, object>>
to Expression<Func<object>>
?
For example:
public class Entity
{
public virtual long Id { get; set; }
}
Origin:
Expression<Func<Entity, object>> origin = x => x.Id;
Destination:
Entity alias = null;
Expression<Func<object>> destination = () => alias.Id;
Actually I'm trying to create a custom cacheable ResultTransformer for Nhibernate. There is a method public QueryOverProjectionBuilder<T> WithAlias(Expression<Func<object>> alias);
But in my classes for each particular entitites I would like to use more specific selector like Expression<Func<T, object>>
Upvotes: 0
Views: 1836
Reputation: 5790
You have two options:
Option 1 is as simple as Expression.Invoke
but may not be compatible with libraries such as LINQ. Option 2 is best done using an expression visitor:
private class ExchangeParametersVisitor : ExpressionVisitor
{
public ParameterExpression Parameter { get; set; }
public Expression Value { get; set; }
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == Parameter)
{
return Value;
}
return node;
}
}
What you need to do is apply the visitor to the body of your lambda expression and use it to create a new lambda expression that contains all parameters as before except the one you replaced.
Upvotes: 1
Reputation: 63772
That's what Expression.Invoke
is for.
Create a new lambda expression, and use Expression.Invoke
on the original expression to compose the two expressions.
Sample:
Expression<Func<string, int>> inner = x => int.Parse(x);
var outer = Expression.Lambda<Func<int>>
(Expression.Invoke(inner, Expression.Constant("123")));
outer.Compile()().Dump(); // 123
Sadly, some expression parsers don't handle Invoke
correctly - they assume it to be an invocation of a method, and reject it. In that case, you need to inline the expression. That means visiting the whole inner expression and replacing the ParameterExpression
s with variables in the better case, or if parser doesn't support that either, inlining the argument in all the places.
Upvotes: 1