views:

49

answers:

3

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 ?

A: 

The JavaScript code you posted doesn’t parse. Could it be that your particular JavaScript interpreter is very lenient and reinterprets the call as myClass.Do('str')? That would explain the nulls.

Timwi
A: 

In .NET 4.0, specify that the second param is dynamic and you should get an object reference you can work with. In 3.5 and below, it'll be a JsObject of some kind, but the entire Microsoft.JScript namespace isn't supposed to be used directly so I'm not too sure if you can specify that you'll be taking a JsObject.

Is "key" supposed to be a string literal or the name of another variable? You're also missing a closing quote on "Testing". I seriously doubt that JS will compile correctly exactly as written.

KeithS
Thank you but i have tried the "dynamic" also but does not work. BTW I'm using jint not Microsoft.JScript ns.
Ertan
A: 

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);
Jason Goemaat
which version are you using ? I have tried the exact sample with v0.8.8 of jint but o argument is still null in JSFindAll method.
Ertan
Sorry, I forgot I had changed one method from the 0.8.8 source code. I've edited the answer to include the changed code, and it is on the JINT site if you browse the source.
Jason Goemaat