From f1f9e470fc219c04eada98db9a7c70a7f7fbb307 Mon Sep 17 00:00:00 2001 From: EDR Date: Tue, 13 Dec 2016 10:22:04 +0100 Subject: [PATCH] Fix Issue "Nested dynamic objects #54" --- src/DynamicExpresso.Core/Parsing/Parser.cs | 9 +++++-- test/DynamicExpresso.UnitTest/DynamicTest.cs | 27 ++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/DynamicExpresso.Core/Parsing/Parser.cs b/src/DynamicExpresso.Core/Parsing/Parser.cs index a627ad41..6e1b3a96 100644 --- a/src/DynamicExpresso.Core/Parsing/Parser.cs +++ b/src/DynamicExpresso.Core/Parsing/Parser.cs @@ -863,7 +863,7 @@ Expression GeneratePropertyOrFieldExpression(Type type, Expression instance, int Expression.Field(instance, (FieldInfo)member); } - if (IsDynamicType(type)) + if (IsDynamicType(type) || IsDynamicExpression(instance)) return ParseDynamicProperty(type, instance, propertyOrFieldName); throw CreateParseException(errorPos, ErrorMessages.UnknownPropertyOrField, propertyOrFieldName, GetTypeName(type)); @@ -882,7 +882,7 @@ Expression ParseMethodInvocation(Type type, Expression instance, int errorPos, s if (methodInvocationExpression != null) return methodInvocationExpression; - if (IsDynamicType(type)) + if (IsDynamicType(type) || IsDynamicExpression(instance)) return ParseDynamicMethodInvocation(type, instance, methodName, args); throw new NoApplicableMethodException(methodName, GetTypeName(type), errorPos); @@ -1071,6 +1071,11 @@ static bool IsDynamicType(Type type) return typeof(IDynamicMetaObjectProvider).IsAssignableFrom(type); } + static bool IsDynamicExpression(Expression instance) + { + return instance != null && instance.NodeType == ExpressionType.Dynamic; + } + static Type GetNonNullableType(Type type) { return IsNullableType(type) ? type.GetGenericArguments()[0] : type; diff --git a/test/DynamicExpresso.UnitTest/DynamicTest.cs b/test/DynamicExpresso.UnitTest/DynamicTest.cs index b902bb55..02ad23ad 100644 --- a/test/DynamicExpresso.UnitTest/DynamicTest.cs +++ b/test/DynamicExpresso.UnitTest/DynamicTest.cs @@ -21,6 +21,19 @@ public void Get_Property_of_an_ExpandoObject() Assert.AreEqual(dyn.Foo, interpreter.Eval("dyn.Foo")); } + [Test] + public void Get_Property_of_a_nested_ExpandoObject() + { + dynamic dyn = new ExpandoObject(); + dyn.Sub = new ExpandoObject(); + dyn.Sub.Foo = "bar"; + + var interpreter = new Interpreter() + .SetVariable("dyn", dyn); + + Assert.AreEqual(dyn.Sub.Foo, interpreter.Eval("dyn.Sub.Foo")); + } + //[Test] //public void Set_Property_of_an_ExpandoObject() //{ @@ -58,6 +71,20 @@ public void Invoke_Method_of_an_ExpandoObject() Assert.AreEqual(dyn.Foo(), interpreter.Eval("dyn.Foo()")); } + + [Test] + public void Invoke_Method_of_a_nested_ExpandoObject() + { + dynamic dyn = new ExpandoObject(); + dyn.Sub = new ExpandoObject(); + dyn.Sub.Foo = new Func(() => "bar"); + + var interpreter = new Interpreter() + .SetVariable("dyn", dyn); + + Assert.AreEqual(dyn.Sub.Foo(), interpreter.Eval("dyn.Sub.Foo()")); + } + [Test] public void Standard_methods_have_precedence_over_dynamic_methods() {