Reputation: 3509
I have the class:
public class Uid
{
public Guid Id { get; set; }
}
And i've an expression:
void TestMethod<T, TUid>(Expression<Func<T,IUid>> exp1) where TUid : Uid
{
....
}
I know that exp1.Body
is a PropertyExpression, it's something like that: (s) => s.UidProperty
where UidProperty
is a property of Uid type. Having it I should create the following expression:
Expression<Func<T, Guid>> myExp = (s) => s.UidProperty.Id
How to do that?
Upvotes: 0
Views: 120
Reputation: 203802
We can use the following Compose
method to take an expression that computes a value, and another expression that uses that output type as its input type, to create an expression that represents what would happen if the result of the first expression were passed to the second expression:
public static Expression<Func<TFirstParam, TResult>>
Compose<TFirstParam, TIntermediate, TResult>(
this Expression<Func<TFirstParam, TIntermediate>> first,
Expression<Func<TIntermediate, TResult>> second)
{
var param = Expression.Parameter(typeof(TFirstParam), "param");
var newFirst = first.Body.Replace(first.Parameters[0], param);
var newSecond = second.Body.Replace(second.Parameters[0], newFirst);
return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}
public static Expression Replace(this Expression expression,
Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression from, to;
public ReplaceVisitor(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
return node == from ? to : base.Visit(node);
}
}
This allows us to write:
public Expression<Func<T, Guid>> TestMethod<T, TUid>(
Expression<Func<T,IUid>> expression)
where TUid : Uid
{
return expression.Compose(uid => uid.Id);
}
Upvotes: 3