Skip to content

Instantly share code, notes, and snippets.

@e673
Created July 5, 2017 11:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save e673/6d5a389c7ee87490e3e59d152b0e5ff9 to your computer and use it in GitHub Desktop.
Save e673/6d5a389c7ee87490e3e59d152b0e5ff9 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
namespace Experiments
{
class ExpressionUtil
{
class Substitutor
{
Expression expr;
Expression subst;
ParameterExpression[] param;
ParameterExpression replaced;
public Substitutor(LambdaExpression expr, LambdaExpression subst, int index)
{
this.expr = expr.Body;
this.subst = subst.Body;
replaced = expr.Parameters[index];
param = expr.Parameters.SelectMany((p, i) => i != index ? Enumerable.Repeat(p, 1) : subst.Parameters).ToArray();
}
public LambdaExpression GetResult()
{
Expression res = Traverse(expr);
return Expression.Lambda(res, param);
}
public Expression<T> GetResult<T>()
{
Expression res = Traverse(expr);
return Expression.Lambda<T>(res, param);
}
Expression Traverse(Expression expr)
{
switch (expr)
{
case ParameterExpression pex:
return pex == replaced ? subst : pex;
case UnaryExpression uex:
return uex.Update(Traverse(uex.Operand));
case BinaryExpression bex:
return bex.Update(Traverse(bex.Left), bex.Conversion, Traverse(bex.Right));
case MethodCallExpression mcex:
return mcex.Update(Traverse(mcex.Object), mcex.Arguments.Select(Traverse));
case LambdaExpression lex:
return lex;
case null:
return null;
default:
throw new NotImplementedException();
}
}
}
public static LambdaExpression Substitute(LambdaExpression expr, LambdaExpression subst, int index)
{
Substitutor p = new Substitutor(expr, subst, index);
return p.GetResult();
}
public static Expression<T> Substitute<T>(LambdaExpression expr, LambdaExpression subst, int index)
{
Substitutor p = new Substitutor(expr, subst, index);
return p.GetResult<T>();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment