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

Cannot use Action/Function in PropertBag in JScript/V8

Jun 26, 2014 at 10:45 PM
I have created a new class that inherits a PropertyBag (but tried it direct also) so that I can create some standard Actions or Functions automatically when the Bag is created.
Code Below :
        public class ConfigBag : PropertyBag
        {
            private const String stdkeys = "bagkeys,doit";
            public ConfigBag()
            {
                this["bagkeys"] = new Func<String>(() => this.bagkeys());
                this["doit"] = new Action(() => this.doit());
            }

            public String bagkeys()
            {
                List<String> keys = this.Keys.ToList();
                foreach (String k in stdkeys.Split(new char[] { ',' }))
                {
                    keys.Remove(k);
                }
                return String.Join(",", keys.ToArray());                
            }

            public void doit()
            {
                Debug.Print("Got here : ");
            }
        }

            public ConfigBag newbag()
            {
                ConfigBag bag = new ConfigBag();
                bag.Add("Name", "Richard");
                bag.Add("Age", 21);
                bag.Add("FootBall", "Arsenal");
                return bag;
            }
When I execute this from VBScript
x = api.newbag()
debug.log(x.Name)
debug.log(x.Age)
debug.log(x.bagkeys)
debug.log(x.doit)
It all works fine ...

Name,Age,FootBall

But when I execute it from JScript of V8 (exactly the same code) I get

System.Func`1[System.String]

Hitting my head against a wall here! Am I missing something? I am trying to make a standard interface between VBScript and JScript or V8. I need the PropertyBag type functionality which works but I cannot do things like use ".ContainsKey" plus like the idea of adding additional functionality.
Coordinator
Jun 26, 2014 at 11:06 PM
Hello egooner,

JavaScript syntax requires a parenthesized argument list for invocation:
debug.log(x.bagkeys())
Otherwise you're just printing out the delegate's string representation.

Good luck!
Jun 26, 2014 at 11:07 PM
Ok - so I figured out that if I can from JS using x.bagkeys() instead of x.bagkeys it works!
But am I overcomplicating matters and should x.bagkeys work without the () appended as it does with VBScript?
Jun 26, 2014 at 11:10 PM
Thanks - figured that just before your post but thanks anyway ... am I missing something though? Why can I not access the PropertyBag's own Keys function is that intentional?
                engine.AddHostObject("debug", jsapi.mydebug);          
                engine.AddHostObject("console", jsapi.console);
                engine.AddHostObject("document", jsapi.document);
                engine.AddHostType("IndexedList", typeof(IndexedList<Object>));
                engine.AddHostType("ConfigBag", typeof(ConfigBag));
I did try also with PropertyBag added in the AddHostObject but that did not expose Keys either!?
Coordinator
Jun 27, 2014 at 1:34 PM
Hi egooner,

Why can I not access the PropertyBag's own Keys function is that intentional?

Yes, that's intentional. Property bags are special in that they expose their keys as if they were members. Exposing their members within the same namespace could create conflict or ambiguity.

If you need to enumerate a property bag, you can use JavaScript's for...in statement.

Another possibility is to expose a property bag's dictionary interface separately from the property bag itself:
var foo = new PropertyBag();
engine.AddHostObject("foo", foo);
engine.AddRestrictedHostObject("fooDict", (IDictionary<string, object>)foo);
and then, in JavaScript:
foo.bar = 123;
if (fooDict.Keys.Contains('bar')) {
    // do something
}
Cheers!