Dynamic properties added to DynamicObject are undefined

Feb 24, 2014 at 8:37 AM
Hi,

First, thanks again for an amazing project.

It seems that dynamic properties added to a DynamicObject are not handled correctly.
    class MyDynamicObject : DynamicObject
    {
        private Dictionary<string, object> _dict;
        public MyDynamicObject()
            : base()
        {
            this._dict = new Dictionary<string, object>();
        }

        public string RealProp { get; set; }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            return this._dict.TryGetValue(binder.Name, out result);
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            this._dict[binder.Name] = value;
            return true;
        }
    }


    class DynamicTest
    {
        public void Run()
        {
            using (var engine = new V8ScriptEngine())
            {
                dynamic myDynamicObject = new MyDynamicObject();

                string val = "Value1";
                myDynamicObject.DynProp = val;
                myDynamicObject.RealProp = val;
                
                engine.AddHostObject("myDynamicObject", myDynamicObject);
                engine.AddHostType("Console", typeof(Console));

                Console.WriteLine("myDynamicObject.DynProp = " + myDynamicObject.DynProp);

                Console.WriteLine("myDynamicObject.RealProp = " + myDynamicObject.RealProp);

                // The following print 'undefined'
                engine.Execute("Console.WriteLine('In script: myDynamicObject.DynProp = ' + myDynamicObject.DynProp)");

                engine.Execute("Console.WriteLine('In script: myDynamicObject.RealProp = ' + myDynamicObject.RealProp)");

                // Dynamic properties added to ExpandoObject are OK
                dynamic myExpandoObject = new ExpandoObject();
                myExpandoObject.DynProp = val;
                engine.AddHostObject("myExpandoObject", myExpandoObject);
                engine.Execute("Console.WriteLine('In script: myExpandoObject.DynProp = ' + myExpandoObject.DynProp)");
            }
        }
    }
The output of this test is:
myDynamicObject.DynProp = Value1
myDynamicObject.RealProp = Value1
In script: myDynamicObject.DynProp = undefined
In script: myDynamicObject.RealProp = Value1
In script: myExpandoObject.DynProp = Value1
Note that the same test for ExpandoObject works OK.
It seems to me that ClearScript overrides TryGetMember() without calling base.TryGetMember().

Thanks again,
Ron
Coordinator
Feb 24, 2014 at 12:32 PM
Hi Ron,

To provide scriptable access to the members of a dynamic host object, ClearScript requires that the object provide a correct implementation of GetDynamicMemberNames. In your example, it could look something like this:
public override IEnumerable<string> GetDynamicMemberNames()
{
    return this._dict.Keys;
}
Thanks for your question, and good luck!
Marked as answer by Zcodez on 2/24/2014 at 10:37 PM
Oct 31, 2014 at 10:10 AM
This is awesome.

Works perfectly, but you should considder updating the documentation with it.

Great project!