Last active
November 16, 2020 23:34
-
-
Save aetos382/35bcf275f549a0e324766b74ccbd4603 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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