I recently started messing around with IronJS again, and I must say that this project is pure awesomeness! One of the first things I noticed is that when you call the “Execute” methods to run some JavaScript code it returns an “object.” Now, while this works just fine, I would prefer if it returned a “dynamic” object while running against .NET 4.0. There may be some reason that Fredrik Holmstrom (the author) decided to return an ‘object’, so I don’t mean to sound negative, but you have to admit that dynamics are really cool, especially when working with a dynamic language like JavaScript.
Basics of using IronJS
There are articles that cover the usage of IronJS, but here’s a very brief summary:
// Instantiate the IronJS Engine var context = new IronJS.Hosting.CSharp.Context(); var result = context.Execute("2 + 2");// returns 4 var result = context.Execute("'Ch' + 'ris'"); // returns "Chris"
Returning JavaScript Objects
The previous examples were extremely simple just to give you an idea if you are unfamiliar. Now I will show a more interesting example that returns a JavaScript object instead of just a simple, single value.
var result = context.Execute(@"
(function(){
// do something here
var id = 42;
var name = 'chris';
return { id: id, name: name }
})()");
This returns a JavaScript object with “id” and “name” properties set respectively to 42 and “chris”.
Retrieving Object Values
Retrieving the JavaScript object values is pretty straight forward, although you must reach for them through the “CommonObject.Members” property.
var obj = (CommonObject)result; var id = obj.Members["id"]; var name = obj.Members["name"];
Using Dynamics (via DynamicCommonObject class) to Retrieve Object Values
Wouldn’t it be nice to use Dynamics to get at the JavaScript object values? Yes, I agree that it would be.
Here’s an example of performing the previous example by using the DynamicCommonObject wrapper class (code listed below) to do it with .NET 4.0’s Dynamic object support.
var obj = new DynamicCommonObject(result as CommonObject);// like properties on the object var id = obj.id; var name = obj.name;// using the indexer property (not dynamic, but also simpler) var id = obj["id"]; var name = obj["name"];
What if the property doesn’t exist? Well let me show you…
var firstname = obj.firstname;// throws RuntimeBinderException with message:// "'DynamicCommonObject' does not contain a definition for 'notexist'" var firstname = obj["firstname"]; // returns IronJS.Undefined
If you want to change the behavior of DynamicCommonObject when the requested property name does not exist, then you can modify it’s code; it’s listed below.
DynamicCommonObject Wrapper Class Source Code
// Copyright (c) 2011 Chris Pietschmann - http://pietschsoft.com// This work is licensed under a Creative Commons Attribution 3.0 Unites States License// http://creativecommons.org/licenses/by/3.0/us/using System;using System.Collections;using System.Collections.Generic;using System.Dynamic;using System.Linq;using IronJS;publicclass DynamicCommonObject : DynamicObject, IEnumerable, IEnumerable<KeyValuePair<string, object>>, IDictionary<string, object> {public DynamicCommonObject(CommonObject commonObject) {this.CommonObject = commonObject; }public CommonObject CommonObject { get; private set; }#region"DynamicObject Overrides"publicoverridebool TryGetMember(GetMemberBinder binder, outobject result) { var r = this.Keys.Contains(binder.Name) ? this[binder.Name] : null; result = getClrBoxedValue(r);if (result == null) {returnfalse; }returntrue; }publicoverridebool TrySetMember(SetMemberBinder binder, objectvalue) {this.CommonObject.Put(binder.Name, value);returntrue; }publicoverride IEnumerable<string> GetDynamicMemberNames() {returnthis.CommonObject.Members.Keys; }#endregion#region"IEnumerable<KeyValuePair<string, object>> Implementation"public IEnumerator<KeyValuePair<string, object>> GetEnumerator() {returnthis.CommonObject.Members.Select(d => new KeyValuePair<string, object>(d.Key, getClrBoxedValue(d.Value))).AsEnumerable().GetEnumerator(); } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { returnthis.GetEnumerator(); }#endregion#region"IDictionary Implementation"publicvoid Add(string key, objectvalue) {this.CommonObject.Put(key, value); }publicbool ContainsKey(string key) {returnthis.CommonObject.Members.Keys.Contains(key); }public ICollection<string> Keys { get { returnthis.CommonObject.Members.Keys; } }publicbool Remove(string key) {returnthis.CommonObject.Members.Remove(key); }publicbool TryGetValue(string key, outobjectvalue) {object v; var retVal = this.CommonObject.Members.TryGetValue(key, out v);value = getClrBoxedValue(v);return retVal; }public ICollection<object> Values { get {returnthis.CommonObject.Members.Values.Select(d => getClrBoxedValue(d)).ToArray(); } }publicobjectthis[string key] { get {return getClrBoxedValue(this.CommonObject.Get(key)); } set {this.CommonObject.Put(key, value); } }publicvoid Add(KeyValuePair<string, object> item) {this.CommonObject.Members.Add(item.Key, item.Value); }publicvoid Clear() {this.CommonObject.Members.Clear(); }publicbool Contains(KeyValuePair<string, object> item) {returnthis.CommonObject.Members.Contains(item); }publicvoid CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) {thrownew NotImplementedException(); }publicint Count { get { returnthis.CommonObject.Members.Count; } }publicbool IsReadOnly { get { returnfalse; } }publicbool Remove(KeyValuePair<string, object> item) { var v = this.CommonObject.Members[item.Key];if (v == item.Value) {returnthis.CommonObject.Members.Remove(item.Key); }returnfalse; }#endregion#region"Static Methods"privatestaticobject getClrBoxedValue(object obj) {if (obj is IronJS.BoxedValue) {return ((IronJS.BoxedValue)obj).ClrBoxed; }return obj; }#endregion }
More Information on IronJS
If you aren’t familiar with IronJS, I encourage you to go check out one or more of the following links:
- http://ironjs.wordpress.com/
- Hanselminutes Podcast 271: Inside IronJS – A complete JavaScript/ECMAScript open source implementation on the .NET DLR
- https://github.com/fholm/IronJS/wiki