Skip to content

Instantly share code, notes, and snippets.

@Pzixel
Created September 5, 2019 13:47
Show Gist options
  • Save Pzixel/2af7d65ea9dbd5680f654725a4917d90 to your computer and use it in GitHub Desktop.
Save Pzixel/2af7d65ea9dbd5680f654725a4917d90 to your computer and use it in GitHub Desktop.
void Main()
{
var foo = new C { B = new B { A = new A() }};
var helper = ExpressionHelper<C>.GetDelegate<A>("B.A");
helper(foo).Dump();
}
class A {
public int X => 10;
}
class B {
public A A { get; set; }
}
class C {
public B B { get; set; }
}
public static class ExpressionHelper<T>
{
private class ExpressionHolder<V> {
public static Dictionary<string, (Expression<Func<T, V>>, Func<T, V>)> CachedExpressions = new Dictionary<string, (System.Linq.Expressions.Expression<System.Func<T, V>>, System.Func<T, V>)>();
}
public static Expression<Func<T, V>> GetExpression<V>(string path) => GetCachedExpression<V>(path).expression;
public static Func<T, V> GetDelegate<V>(string path) => GetCachedExpression<V>(path).compiledExpression;
private static (Expression<Func<T, V>> expression, Func<T, V> compiledExpression) GetCachedExpression<V>(string path)
{
if (ExpressionHolder<V>.CachedExpressions.TryGetValue(path, out var result))
{
return result;
}
var parameter = Expression.Parameter(typeof(T));
var fieldsAccesses = path.Split('.');
Debug.Assert(fieldsAccesses.Length > 0);
var accesses = fieldsAccesses.Aggregate((Expression) parameter, (x, field) => Expression.PropertyOrField(x, field));
var expression = Expression.Lambda<Func<T, V>>(accesses, parameter);
var compiledExpression = expression.Compile();
ExpressionHolder<V>.CachedExpressions[path] = (expression, compiledExpression);
return (expression, compiledExpression);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment