Skip to content

Instantly share code, notes, and snippets.

@aetos382
Last active November 16, 2020 23:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aetos382/35bcf275f549a0e324766b74ccbd4603 to your computer and use it in GitHub Desktop.
Save aetos382/35bcf275f549a0e324766b74ccbd4603 to your computer and use it in GitHub Desktop.
private static void Main()
{
Expression<Func<Hoge, Hoge>> expression = x => new Hoge(x.i + 9)
{
a = new[] { 8, 9, x.i * 2 }
};
expression.Dump();
var rewrited = Bind(expression, new Hoge(10));
rewrited.Dump();
var d = (Func<Hoge>)rewrited.Compile();
var instance = d();
instance.Dump();
}
public static Expression<Func<T>> Bind<T>(
Expression<Func<T, T>> expression,
T value)
{
var visitor = new ExpressionParameterBinder<T>(value, expression.Parameters[0]);
var rewrited = visitor.Visit(expression.Body);
var newLambda = Expression.Lambda<Func<T>>(rewrited);
return newLambda;
}
internal class Hoge
{
public Hoge(int i)
{
this.i = i;
}
public int i { get; }
public int[] a { get; set; }
public int GetHoge()
{
return 3333;
}
}
internal class ExpressionParameterBinder<T> :
ExpressionVisitor
{
private readonly T _original;
private readonly ParameterExpression _parameter;
private readonly Dictionary<MemberInfo, ConstantExpression> _cache =
new Dictionary<MemberInfo, ConstantExpression>();
public ExpressionParameterBinder(
T original,
ParameterExpression parameter)
{
this._original = original;
this._parameter = parameter;
}
protected override Expression VisitMember(
MemberExpression node)
{
if (node.Expression != this._parameter)
{
return node;
}
var member = node.Member;
if (!this._cache.TryGetValue(member, out var evaluatedExpression))
{
object value = null;
if (member is PropertyInfo p)
{
value = p.GetValue(this._original);
}
else if (member is FieldInfo f)
{
value = f.GetValue(this._original);
}
this._cache[member] = evaluatedExpression = Expression.Constant(value);
}
return evaluatedExpression;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment