Host Function that returns dynamic object

Sep 19, 2016 at 3:36 PM

I am trying to access properties from a dynamic object that is returned from a c# call.
Example JS:
var xml = api.MyHostFunction();
var productId = xml.ProductId;
This is the prototype for MyHostFunction():
dynamic MyHostFunction();
ClearScript is throwing an exception when trying to access the ProductId property.
Debugging I can see that the property actually exists and can be accessed from any Host code. But its not possible to access it from JS:

TypeError: Cannot read property 'ProductId' of undefined

Am I doing anything wrong or ClearScript does not support this yet?

Thank you!
Sep 19, 2016 at 3:44 PM

What kind of object does MyHostFunction actually return? Also, are you using V8 or JScript?

Sep 19, 2016 at 4:00 PM

Thank you for the prompt reply.

The object is typeof(dynamic).
That function makes a call to my WebServer and retrieves a XML document. This XML document can be a lot of different things, so to ease parsing, I am converting it to a dynamic object as described here:
Then, my JS code should be able to access the XML document elements and attributes as dynamic C# properties.

Basically it is an object that inherits from the DynamicObject class.

I am running V8 engine.
Sep 19, 2016 at 4:17 PM
Hi again,

For this to work, your object must implement GetDynamicMemberNames in addition to TryGetMember et al.

Good luck!
Sep 19, 2016 at 6:37 PM

Implementing this method worked.
I will paste it here for future reference:
public class DynamicXml : DynamicObject, IEnumerable
        private readonly List<XElement> _elements;

        public DynamicXml(string text)
            var doc = XDocument.Parse(text);
            _elements = new List<XElement> { doc.Root };

        protected DynamicXml(XElement element)
            _elements = new List<XElement> { element };

        protected DynamicXml(IEnumerable<XElement> elements)
            _elements = new List<XElement>(elements);

        public override bool TryGetMember(GetMemberBinder binder, out object result)
            result = null;
            var attr = _elements[0].Attribute(XName.Get(binder.Name));
            if (attr != null)
                result = attr.Value;
                var items = _elements.Descendants(XName.Get(binder.Name));
                if (items == null || items.Count() == 0) 
                    return false;
                result = new DynamicXml(items);
            return true;

        public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
            int ndx = (int)indexes[0];
            result = new DynamicXml(_elements[ndx]);
            return true;

        public override IEnumerable<string> GetDynamicMemberNames()
            List<String> memberNames = new List<String>();
            foreach (XAttribute attr in _elements[0].Attributes())
            foreach (XElement child in _elements[0].Descendants())
            return memberNames;

        public IEnumerator GetEnumerator()
            foreach (var element in _elements)
                yield return new DynamicXml(element);