Advertisement
RupertAvery

ExpressionEval Extensions

Aug 20th, 2014
367
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.96 KB | None | 0 0
  1.     public class Scope
  2.     {
  3.         public int A { get; set; }
  4.         public int B { get; set; }
  5.         public int C { get; set; }
  6.     }
  7.  
  8.     public class ExpressionObject<TScope, TValue>
  9.     {
  10.         public string StringExpression { get; set; }
  11.         public Expression ExpressionTree { get; set; }
  12.         public Func<TScope, TValue> CompiledFunction { get; set; }
  13.     }
  14.  
  15.     public class ExpressionExtension<TScope, TValue>
  16.     {
  17.         private Dictionary<string, ExpressionObject<TScope, TValue>> atomLookup;
  18.         private TScope scope;
  19.  
  20.         public ExpressionExtension(TScope scope)
  21.         {
  22.             atomLookup = new Dictionary<string, ExpressionObject<TScope, TValue>>();
  23.             this.scope = scope;
  24.         }
  25.  
  26.         private void ResolveDependencies(Expression expression)
  27.         {
  28.             if (typeof (BinaryExpression).IsAssignableFrom(expression.GetType()) )
  29.             {
  30.                 var bexp = ((BinaryExpression)expression);
  31.                 ResolveDependencies(bexp.Left);
  32.                 ResolveDependencies(bexp.Right);
  33.             }
  34.             else if (expression.GetType() == typeof (UnaryExpression))
  35.             {
  36.                 var bexp = ((UnaryExpression)expression);
  37.                 ResolveDependencies(bexp.Operand);
  38.             }
  39.             else if (typeof(MemberExpression).IsAssignableFrom(expression.GetType()))
  40.             {
  41.                 var pexp = ((MemberExpression)expression).Member;
  42.  
  43.                 ExpressionObject<TScope, TValue> expressionObject;
  44.  
  45.                 if (atomLookup.TryGetValue(pexp.Name, out expressionObject))
  46.                 {
  47.                     var bexp = ((BinaryExpression)expressionObject.ExpressionTree).Right;
  48.                     ResolveDependencies(bexp);
  49.                     expressionObject.CompiledFunction(scope);
  50.                 }
  51.             }
  52.         }
  53.  
  54.         public TValue Eval(string expression)
  55.         {
  56.             Console.WriteLine("Executing: {0}", expression);
  57.  
  58.             var comp = new CompiledExpression<TValue>(expression);
  59.             // build the expression, but do not compile its
  60.             comp.GenerateLambda<Func<TScope, TValue>, TScope>(true, false);
  61.  
  62.             if (comp.Expression.NodeType == ExpressionType.Assign)
  63.             {
  64.                 var exp = ((BinaryExpression) comp.Expression);
  65.  
  66.                 if (exp.Left.NodeType == ExpressionType.MemberAccess)
  67.                 {
  68.                     var mexp = ((MemberExpression) exp.Left).Expression;
  69.  
  70.                     if (mexp.NodeType == ExpressionType.Parameter)
  71.                     {
  72.                         if (((ParameterExpression) mexp).Name == "scope")
  73.                         {
  74.                             var pexp = ((MemberExpression) exp.Left).Member;
  75.  
  76.                             ExpressionObject<TScope, TValue> expressionObject;
  77.  
  78.                             if (!atomLookup.TryGetValue(pexp.Name, out expressionObject))
  79.                             {
  80.                                 expressionObject = new ExpressionObject<TScope, TValue>()
  81.                                     {
  82.                                         CompiledFunction = comp.ScopeCompile<TScope>(),
  83.                                         ExpressionTree = comp.Expression,
  84.                                         StringExpression = expression
  85.                                     };
  86.  
  87.                                 // ideally we should be able to compile the expression without have to re-parse
  88.                                 atomLookup.Add(pexp.Name, expressionObject);
  89.                             }
  90.  
  91.                             if (expressionObject.StringExpression != expression)
  92.                             {
  93.                                 expressionObject.CompiledFunction = comp.ScopeCompile<TScope>();
  94.                                 expressionObject.ExpressionTree = comp.Expression;
  95.                                 expressionObject.StringExpression = expression;
  96.                             }
  97.  
  98.                             return default(TValue);
  99.                         }
  100.                     }
  101.                 }
  102.  
  103.             }
  104.             else
  105.             {
  106.                 ResolveDependencies(comp.Expression);
  107.                 return comp.ScopeCompile<TScope>()(scope);
  108.             }
  109.  
  110.             throw new Exception();
  111.             //return func(scope);
  112.         }
  113.     }
  114.  
  115.  
  116.     class Program
  117.     {
  118.         static void Main(string[] args)
  119.         {
  120.             var scope = new Scope();
  121.             var ee = new ExpressionExtension<Scope, int>(scope);
  122.             ee.Eval("A = 10");
  123.             ee.Eval("B = A + 10");
  124.             ee.Eval("C = A + B");
  125.             Console.WriteLine(ee.Eval("B"));  // Expect 20
  126.             Console.WriteLine(ee.Eval("C"));  // Expect 30
  127.             ee.Eval("A = 20");
  128.             Console.WriteLine(ee.Eval("B"));  // Expect 30
  129.             Console.WriteLine(ee.Eval("C"));  // Expect 50
  130.             Console.ReadLine();
  131.         }
  132.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement