0

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?

1 Answer 1

3

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); 
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.