I’ve been writing some unit tests lately that require quite a bit of casting. This gets tiring pretty fast so I went ahead and decided to give the dynamic keyword a try. I’ll show the before and after examples and let you decide.
Here is the non-dynamic version.
[Test] public void InvokeWithAddPlusInvokeTest() { string code = "f(1 + 2) + g()"; var b1 = (BinaryExpression)this.pipeline.Compile(code); var f = (MethodInvokeExpression)b1.Left; var g = (MethodInvokeExpression)b1.Right; var b2 = (BinaryExpression)f.Parameters.Single(); var one = (PrimitiveExpression)b2.Left; var two = (PrimitiveExpression)b2.Right; Assert.That(b1.Operator == BinaryOperator.Add); Assert.That(b2.Operator == BinaryOperator.Add); Assert.That(((ReferenceExpression)f.Target).Name == "f"); Assert.That(((ReferenceExpression)g.Target).Name == "g"); Assert.That(one.Value == "1"); Assert.That(two.Value == "2"); }
In this test I am compiling an expression into an AST and digging around to verify that the correct nodes were created in the right places in the tree.
Here is the dynamic version.
[Test] public void InvokeWithAddPlusInvokeTest() { string code = "f(1 + 2) + g()"; dynamic b1 = this.pipeline.Compile(code); dynamic b2 = Enumerable.Single(b1.Left.Parameters); Assert.That(b1.Operator == BinaryOperator.Add); Assert.That(b2.Operator == BinaryOperator.Add); Assert.That(b1.Left.Target.Name == "f"); Assert.That(b1.Right.Target.Name == "g"); Assert.That(b2.Left.Value == "1"); Assert.That(b2.Right.Value == "2"); }
A lot shorter that’s for sure. The only downside is that if I change the nodes I will no longer get compile time warnings… but I will get unit test errors so this shouldn’t theoretically matter. I also no longer get intellisense so I either have to just know the structure of the objects or use the debugger to figure it out. Still the simplicity is looking good.