Search code examples
c#javascriptjint

Passing a javascript object to c# in jint


I'm trying to send a javascript object to c# world but i cannot figure out how is done.

Here is my javascript code

myClass.Do( 'str', { key : 'Testing' } );

And I have tried to these method signatures on c# class, first parameter is correct but second parameter is always null.

public Do(string param1, object param2); // param1 = 'str', param2 = null
public Do(string param1, dynamic param2); // param1 = 'str', param2 = null
public Do(string param1, JsObject param2); // param1 = 'str', param2 = null
public Do(string param1, JsDictionary param2); // param1 = 'str', param2 = null
public Do(string param1, ArgumentClass param2); // param1 = 'str', param2 = null
public Do(string param1, object[] param2); // throws method not found

Is there any way to do this ?


Solution

  • I had to modify this method in Native\JsClr.cs

    public static object ConvertParameter(JsInstance parameter)
    {
        if (parameter.Class != JsFunction.TYPEOF && parameter.Class != JsArray.TYPEOF && parameter.Class != JsObject.TYPEOF)
        {
            return parameter.Value;
        }
        else if (parameter == JsNull.Instance)
        {
            return null;
        }
        else
        {
            JsFunction constructor = ((JsDictionaryObject)parameter)["constructor"] as JsFunction;
            if (constructor == null) return parameter;
    
            switch (constructor.Name)
            {
                case "Date":
                    return JsDateConstructor.CreateDateTime(parameter.ToNumber());
                case "String":
                case "RegExp":
                case "Number":
                    return parameter.Value;
                case "Array":
                    object[] array = new object[((JsObject)parameter).Length];
                    foreach (KeyValuePair<string, JsInstance> key in (JsObject)parameter)
                    {
                        int index = 0;
                        if (int.TryParse(key.Key, out index))
                        {
                            array[index] = ConvertParameters(key.Value)[0];
                        }
                    }
                    return array;
                case "Object":
    
                    if (parameter.Class == JsFunction.TYPEOF) return parameter;
    
                    Dictionary<string, object> dic = new Dictionary<string, object>();
                    foreach (KeyValuePair<string, JsInstance> key in (JsObject)parameter)
                    {
                        dic.Add(key.Key, ConvertParameter(key.Value));
                    }
                    return dic;
                default:
                    return parameter;
            }
        }
    
    }
    

    Here's the function setup:

    m_Engine = new JintEngine(Options.Ecmascript3);
    m_Engine.SetFunction("Compute", new Jint.Delegates.Func<object, object>(JSCompute));
    

    In the method I cast the parameter to Dictionary to get the values but return a constructed JsObject. If any of the properties are objects themselves, you can cast them as Dictionary also:

    public object JSCompute(object o)
    {
        Dictionary<string, object> properties = (Dictionary<string, object>)o;
        double x = (int)((double)properties["X"]);
        double y = (int)((double)properties["Y"]);
        double width = (int)((double)properties["Width"]);
        double height = (int)((double)properties["Height"]);
    
        JsObject results = new JsObject();
        results["Area"] = new JsNumber(width * height);
        results["Diagonal"] = new JsNumber(Math.Sqrt(x * x + y * y));
        return results;
    }
    

    Here's the javascript:

    var rectangle = { "X": 5, "Y": 10, "Width": 20, "Height": 10 };
    var result = Compute(rectangle);
    alert('Area is ' + result.Area + ', Diagonal is ' + result.Diagonal);