// From below CodeProject article // https://www.codeproject.com/Articles/894936/Manipulate-your-expression-trees-with-elegance using System; using System.Linq.Expressions; using System.Reflection; namespace ManipulateExpressionTrees { public static class ReflectionHelpers { public static Expression GetRidOfCompile(this Expression expression) { var visitor = new CompileMethodVisitor(); return Expression.Lambda( visitor.Visit(expression.Body), expression.Parameters); } public static Expression GetRidOfInterfaceCast(this Expression expression) { var visitor = new InterfaceCastVisitor(); return Expression.Lambda( visitor.Visit(expression.Body), expression.Parameters); } private class CompileMethodVisitor : ExpressionVisitor { protected override Expression VisitInvocation(InvocationExpression node) { if (node.NodeType != ExpressionType.Invoke) return base.VisitInvocation(node); var source = node.Expression as MethodCallExpression; if (source == null) return base.VisitInvocation(node); var methodInfo = source.Method; if (methodInfo.DeclaringType == null || !methodInfo.DeclaringType.IsGenericType) return base.VisitInvocation(node); var methodDeclaringType = methodInfo.DeclaringType.GetGenericTypeDefinition(); if (methodDeclaringType != typeof(Expression<>)) return base.VisitInvocation(node); var expr = (LambdaExpression)Evaluate(source.Object); var body = expr.Body; for (int i = 0; i < expr.Parameters.Count; i++) { var visitor = new ParameterUpdateVisitor(expr.Parameters[i], node.Arguments[i]); body = visitor.Visit(body); } return body; } private object Evaluate(Expression exp) { return Expression.Lambda(exp).Compile().DynamicInvoke(); } } private class InterfaceCastVisitor : ExpressionVisitor { protected override Expression VisitMember(MemberExpression node) { var interfaceProperty = node.Member; if (interfaceProperty.MemberType != MemberTypes.Property) return base.VisitMember(node); var interfaceType = interfaceProperty.DeclaringType; if (interfaceType == null || !interfaceType.IsInterface) return base.VisitMember(node); var interfaceCast = node.Expression as UnaryExpression; if (interfaceCast == null || interfaceCast.NodeType != ExpressionType.Convert) return base.VisitMember(node); var instanceType = interfaceCast.Operand.Type; var instanceProperty = GetImplementedProperty(instanceType, interfaceProperty); return Expression.MakeMemberAccess( base.Visit(interfaceCast.Operand), instanceProperty); } private PropertyInfo GetImplementedProperty(Type classType, MemberInfo interfaceProperty) { return classType.GetProperty(interfaceProperty.Name); } } /// /// updates the parameter in the expression /// private class ParameterUpdateVisitor : ExpressionVisitor { private readonly ParameterExpression oldParameter; private readonly Expression newParameter; public ParameterUpdateVisitor(ParameterExpression oldParameter, Expression newParameter) { this.oldParameter = oldParameter; this.newParameter = newParameter; } protected override Expression VisitParameter(ParameterExpression node) { if (object.ReferenceEquals(node, oldParameter)) return newParameter; return base.VisitParameter(node); } } } }