Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class Scope
- {
- public int A { get; set; }
- public int B { get; set; }
- public int C { get; set; }
- }
- public class ExpressionObject<TScope, TValue>
- {
- public string StringExpression { get; set; }
- public Expression ExpressionTree { get; set; }
- public Func<TScope, TValue> CompiledFunction { get; set; }
- }
- public class ExpressionExtension<TScope, TValue>
- {
- private Dictionary<string, ExpressionObject<TScope, TValue>> atomLookup;
- private TScope scope;
- public ExpressionExtension(TScope scope)
- {
- atomLookup = new Dictionary<string, ExpressionObject<TScope, TValue>>();
- this.scope = scope;
- }
- private void ResolveDependencies(Expression expression)
- {
- if (typeof (BinaryExpression).IsAssignableFrom(expression.GetType()) )
- {
- var bexp = ((BinaryExpression)expression);
- ResolveDependencies(bexp.Left);
- ResolveDependencies(bexp.Right);
- }
- else if (expression.GetType() == typeof (UnaryExpression))
- {
- var bexp = ((UnaryExpression)expression);
- ResolveDependencies(bexp.Operand);
- }
- else if (typeof(MemberExpression).IsAssignableFrom(expression.GetType()))
- {
- var pexp = ((MemberExpression)expression).Member;
- ExpressionObject<TScope, TValue> expressionObject;
- if (atomLookup.TryGetValue(pexp.Name, out expressionObject))
- {
- var bexp = ((BinaryExpression)expressionObject.ExpressionTree).Right;
- ResolveDependencies(bexp);
- expressionObject.CompiledFunction(scope);
- }
- }
- }
- public TValue Eval(string expression)
- {
- Console.WriteLine("Executing: {0}", expression);
- var comp = new CompiledExpression<TValue>(expression);
- // build the expression, but do not compile its
- comp.GenerateLambda<Func<TScope, TValue>, TScope>(true, false);
- if (comp.Expression.NodeType == ExpressionType.Assign)
- {
- var exp = ((BinaryExpression) comp.Expression);
- if (exp.Left.NodeType == ExpressionType.MemberAccess)
- {
- var mexp = ((MemberExpression) exp.Left).Expression;
- if (mexp.NodeType == ExpressionType.Parameter)
- {
- if (((ParameterExpression) mexp).Name == "scope")
- {
- var pexp = ((MemberExpression) exp.Left).Member;
- ExpressionObject<TScope, TValue> expressionObject;
- if (!atomLookup.TryGetValue(pexp.Name, out expressionObject))
- {
- expressionObject = new ExpressionObject<TScope, TValue>()
- {
- CompiledFunction = comp.ScopeCompile<TScope>(),
- ExpressionTree = comp.Expression,
- StringExpression = expression
- };
- // ideally we should be able to compile the expression without have to re-parse
- atomLookup.Add(pexp.Name, expressionObject);
- }
- if (expressionObject.StringExpression != expression)
- {
- expressionObject.CompiledFunction = comp.ScopeCompile<TScope>();
- expressionObject.ExpressionTree = comp.Expression;
- expressionObject.StringExpression = expression;
- }
- return default(TValue);
- }
- }
- }
- }
- else
- {
- ResolveDependencies(comp.Expression);
- return comp.ScopeCompile<TScope>()(scope);
- }
- throw new Exception();
- //return func(scope);
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- var scope = new Scope();
- var ee = new ExpressionExtension<Scope, int>(scope);
- ee.Eval("A = 10");
- ee.Eval("B = A + 10");
- ee.Eval("C = A + B");
- Console.WriteLine(ee.Eval("B")); // Expect 20
- Console.WriteLine(ee.Eval("C")); // Expect 30
- ee.Eval("A = 20");
- Console.WriteLine(ee.Eval("B")); // Expect 30
- Console.WriteLine(ee.Eval("C")); // Expect 50
- Console.ReadLine();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement