using System.Linq.Expressions;
using System.Collections.Generic;
using AgileObjects.ReadableExpressions;
public class LambdaConverter<TArg, TReturnType> : ExpressionVisitor
private Type? NewArgType { get; set; } = null;
public Expression<Func<TNewArg, TReturnType>> CastArgTo<TNewArg>(Expression<Func<TArg, TReturnType>> lambda)
NewArgType = typeof(TNewArg);
return (Expression<Func<TNewArg, TReturnType>>)base.Visit(lambda);
protected override Expression VisitParameter(ParameterExpression node)
Console.WriteLine("Visiting param");
Console.WriteLine($"Returning different param of new arg type {NewArgType.Name}");
return Expression.Parameter(NewArgType);
public int Value { get; init; } = 123;
public override string ToString() => "BaseEntity";
public class Foo : BaseEntity
public override string ToString() => "Foo";
public static void Main()
Expression<Func<BaseEntity,int>> original = foo => foo.Value;
BaseEntity b = new Foo();
var converter = new LambdaConverter<BaseEntity,int>();
var converted = converter.CastArgTo<Foo>(original);