diff --git a/src/Spring/Spring.Core/Expressions/PropertyOrFieldNode.cs b/src/Spring/Spring.Core/Expressions/PropertyOrFieldNode.cs index 476e0b30..46a4a9f6 100644 --- a/src/Spring/Spring.Core/Expressions/PropertyOrFieldNode.cs +++ b/src/Spring/Spring.Core/Expressions/PropertyOrFieldNode.cs @@ -22,6 +22,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Reflection; using System.Runtime.Remoting; using System.Runtime.Serialization; @@ -87,8 +88,17 @@ namespace Spring.Expressions // initialize this node if necessary if (contextType != null && accessor == null) { + // try to initialize node as ExpandoObject value +#if NET_4_0 + if (contextType == typeof(System.Dynamic.ExpandoObject)) +#else + if(context.ToString() == "System.Dynamic.ExpandoObject") +#endif + { + accessor = new ExpandoObjectValueAccessor(memberName); + } // try to initialize node as enum value first - if (contextType.IsEnum) + else if (contextType.IsEnum) { try { @@ -695,6 +705,42 @@ namespace Spring.Expressions #endregion + #region ExpandoObjectValueAccessor implementation + + private class ExpandoObjectValueAccessor : BaseValueAccessor + { + private string memberName; + + public ExpandoObjectValueAccessor(string memberName) + { + this.memberName = memberName; + } + + public override object Get(object context) + { + var dictionary = context as IDictionary; + + object value; + if (dictionary.TryGetValue(memberName, out value)) + return value; +#if NET_4_0 + throw new InvalidPropertyException(typeof(System.Dynamic.ExpandoObject), memberName, + "'" + memberName + + "' node cannot be resolved for the specified context [" + + context + "]."); +#else + throw new InvalidPropertyException("'" + memberName + "' node cannot be resolved for the specified context [" + context + "]."); +#endif + } + + public override void Set(object context, object value) + { + throw new NotSupportedException("Cannot set the value of an expando object."); + } + } + + #endregion + #region TypeValueAccessor implementation private class TypeValueAccessor : BaseValueAccessor diff --git a/test/Spring/Spring.Core.Tests/Expressions/ExpressionEvaluatorTests.cs b/test/Spring/Spring.Core.Tests/Expressions/ExpressionEvaluatorTests.cs index ddea487e..54931d03 100644 --- a/test/Spring/Spring.Core.Tests/Expressions/ExpressionEvaluatorTests.cs +++ b/test/Spring/Spring.Core.Tests/Expressions/ExpressionEvaluatorTests.cs @@ -293,8 +293,37 @@ namespace Spring.Expressions object value = ExpressionEvaluator.GetValue(null, "'123' + 1"); Assert.AreEqual("1231", value); } - - [Test(Description="SPRNET-944")] +#if NET_4_0 + [Test(Description = "SPRNET-1507 - Test 1")] + public void TestExpandoObject() + { + dynamic dynamicObject = new System.Dynamic.ExpandoObject(); + //add property at run-time + dynamicObject.IssueId = "1507"; + + object value = ExpressionEvaluator.GetValue(dynamicObject, "IssueId"); + Assert.AreEqual("1507", value); + } + + [Test(Description = "SPRNET-1507 - Test 2")] + public void TestExpandoObjectWithNotExistedProperty() + { + try + { + dynamic dynamicObject = new System.Dynamic.ExpandoObject(); + + ExpressionEvaluator.GetValue(dynamicObject, "PropertyName"); + Assert.Fail(); + } + catch (InvalidPropertyException ex) + { + Assert.AreEqual( + "'PropertyName' node cannot be resolved for the specified context [System.Dynamic.ExpandoObject].", + ex.Message); + } + } +#endif + [Test(Description = "SPRNET-944")] public void DateTests() { string dateLiteral = (string)ExpressionEvaluator.GetValue(null, "'date'"); diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj index 6deafcd0..0445cd97 100644 --- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj +++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2010.csproj @@ -81,6 +81,7 @@ False ..\..\..\lib\Net\2.0\Common.Logging.dll + False ..\..\..\lib\Net\2.0\nunit.framework.dll