I have a class like this :
public class Person
{
public string Name { get; set; }
public string Email { get; set; }
// ...
}
And I have an other generic class like :
public class MyParentObject<T>
{
public T Item { get; set; }
// ...
}
I have for example an expression like this :
Expression<Func<Person, bool>> expression = p => p.Name == "MyName" && p.Email = "[email protected]"
How can I transform this expression to :
Expression<Func<MyParentObject<Person>, bool>> expression = p => p.Item.Name == "MyName" && p.Item.Email = "[email protected]"
EDIT :
I think my question wasn't enough develop, I would like a method like this :
public static Expression<Func<MyParentObject<T>, bool>> GetParentExpression(Expression<Func<T, bool>> expression)
{
Expression <Func<MyParentObject<T>, bool>> result = // process...
// ...
return result;
}
EDIT :
I must create a new tree expression which will be parsed then by c# mongodb driver. I can't use Invoke an other Compile methods on expression tree.
I think I must use ExpressionVisitor but I don't know how...
You can use Expression.Invoke for that like this
public static Expression<Func<MyParentObject<T>, bool>> GetParentExpression<T>(Expression<Func<T, bool>> expression)
{
Expression<Func<MyParentObject<T>, T>> item = parent => parent.Item;
var result = Expression.Lambda<Func<MyParentObject<T>, bool>>(
Expression.Invoke(expression, item.Body), item.Parameters);
return result;
}
Update: Another way which requires a bit more code, but eliminates the Expression.Invoke
is to use a ExpressionVisitor derived class to replace the parameter of the passed expression like this
public static Expression<Func<MyParentObject<T>, bool>> GetParentExpression<T>(Expression<Func<T, bool>> expression)
{
Expression<Func<MyParentObject<T>, T>> item = parent => parent.Item;
var body = new ParameterExpressionReplacer { source = expression.Parameters[0], target = item.Body }.Visit(expression.Body);
var result = Expression.Lambda<Func<MyParentObject<T>, bool>>(body, item.Parameters);
return result;
}
class ParameterExpressionReplacer : ExpressionVisitor
{
public ParameterExpression source;
public Expression target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == source ? target : base.VisitParameter(node);
}
}