This project has moved. For the latest updates, please go here.

Does it work with dynamic objects

Feb 8, 2014 at 3:07 PM
Edited Feb 8, 2014 at 3:32 PM
Hello,

does this evaluator works with dynamic object. I mean not only expandoObject, but object that inherit from DynamicObject.
I have tried with Expando Object and it worked, but it didn't work when using an object that inherited from DynamicObject.
Is it supported?

below an example:
[TestMethod]
        public void NameValueTest()
        {
            //
            // Expando Objects
            //
            dynamic myObj = new ExpandoObject();
            myObj.User = "testUser";

            CompiledExpression compiler = new CompiledExpression();
            compiler.RegisterType("myObj", myObj);
            compiler.StringToParse = "myObj.User";
            compiler.Compile();
            var result = compiler.Eval();

            Assert.AreEqual(result, "testUser"); //test pass

            //
            // Dynamic Objects
            //
            IList testList = new ArrayList();
            testList.Add(new NameValue<string>() { Name = "User", Value = "testUserdynamic" });
            testList.Add(new NameValue<string>() { Name = "Password", Value = "myPass" });
            dynamic dynamicList = new PropertyExtensibleObject(testList);

            Assert.AreEqual(dynamicList.User, "testUserdynamic"); //test pass 

            compiler = new CompiledExpression();
            compiler.RegisterType("dynamicList", dynamicList);
            compiler.StringToParse = "dynamicList.User";
            compiler.Compile();   //!!!!!!FAILS here with this message : Member not found: PropertyExtensibleObject.User
            result = compiler.Eval();

            Assert.AreEqual(result, "testUser");

        }
here is the code of the dynamicObject used:
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Collections;
using System.Reflection;

namespace Utils
{
    public class PropertyExtensibleObject : DynamicObject
    {
        private Dictionary<string, object> addedProperties = new Dictionary<string, object>();

        public Object Target {get;set;}

        public PropertyExtensibleObject(Object target)
        {
           this.Target = target;
            if (target is IList)
            {
                IList temp = target as IList;

                foreach (Object item in temp)
                {
                    PropertyInfo propertyName = item.GetType().GetProperty("Name");
                    string name = propertyName.GetValue(item).ToString();
                    PropertyInfo propertyValue = item.GetType().GetProperty("Value");
                    string value = propertyValue.GetValue(item).ToString();
                    SetValue(name, value);
                }
            }
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            PropertyInfo property = this.Target.GetType().GetProperty(binder.Name);

            if (property != null)
            {
                result = property.GetValue(this.Target);
            }
            else if (addedProperties.ContainsKey(binder.Name))
            {
                result = addedProperties[binder.Name];
            }
            else
            {
                result = null;
                return false;
            }

            return true;
           
        }

        public void SetValue(string propertyName, Object value)
        {
            PropertyInfo property = this.Target.GetType().GetProperty(propertyName);

            if (property != null)
            {
                property.SetValue(this.Target, value);
            }

            if (addedProperties.ContainsKey(propertyName))
            {
                addedProperties[propertyName] = value;
            }
            else
            {
                addedProperties.Add(propertyName, value);
            }
        }

        //public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
        //{
         
        //}

        
    }
}

`
Feb 8, 2014 at 3:56 PM
Edited Feb 8, 2014 at 3:57 PM
I've cloned the source code and made the correction on my machine:
it's located in ExpressionEvaluator.Operators.OperatorCustomExpressions
at line 38, I've replaced the following
isDynamic = type.Name == "ExpandoObject" || type.Name == "Object" 
with
 isDynamic = type.Name == "ExpandoObject" || type.Name == "Object" || type.BaseType.Name == "DynamicObject";
and then it worked.

perhaps a check if baseType is null could be added
Developer
Feb 12, 2014 at 2:06 AM
Hi,

Thanks for catching this. I wonder if checking for the IDynamicMetaObjectProvider interface is more robust? That way we don't have to worry about deep inheritance.

I've added an extension method;
    internal static class TypeExtensions
    {
        public static bool IsDynamic(this Type type)
        {
            return type.GetInterfaces().Contains(typeof (IDynamicMetaObjectProvider)) ||
                   type == typeof (Object);
        }
    }
and changed the last assert to:
            Assert.AreEqual(result, "testUserDynamic");
It seems to work fine. I have committed the changes