Как передать массив на функцию Javascript из С#?

Я использую объект WebBrowser из WPF, и я вызываю код Javascript на странице, загруженной в браузере следующим образом:

myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, bar.ToArray<string>()});

Теперь функция js должна итератировать по элементам второго параметра (массив строк) и делать вещи соответственно. Единственная проблема заключается в том, что параметр, кажется, не передается как массив js.

Например,

alert(typeof theArray);

предупреждения "Неизвестно".

Каков правильный способ передачи массива в качестве параметра при вызове функции js из CSharp?

Ответ 1

Может быть, передать его как строку json и проанализировать его в функции js

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var json = serializer.Serialize(bar.ToArray<string>());

myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, json });

JS:

function myJsFunc(json) {
   var data = JSON.parse(json);
   // do something with it.
}

http://blogs.microsoft.co.il/blogs/pini_dayan/archive/2009/03/12/convert-objects-to-json-in-c-using-javascriptserializer.aspx

Ответ 2

Это не решает проблему, но решает проблему, если у вас есть только один массив: вы можете отправить произвольное количество параметров функции JavaScript и получить к ним доступ через специальную переменную arguments. Он становится аналогом функции, принимающей переменное количество аргументов с теми же преимуществами и проблемами (например, вам нужно передать массив последним, и, как упоминалось ранее, вы можете передать только один).

Вот пример функции JavaScript:

function foo()
{
    var stringArgs = [];
    for (var i = 0; i < arguments.length; i++)
        stringArgs.push(arguments[i]);

    // do stuff with stringArgs
}

И вы бы назвали его из С# следующим образом:

List<string> arguments = new List<string>();
arguments.Add("foo");
arguments.Add("bar");
webBrowser.InvokeScript("foo", arguments.ToArray());

Ответ 3

Если вы действительно хотите выжать каждый бит производительности из кода, вы можете избежать десериализации с помощью eval внутри javascript. Концепция состоит в том, чтобы структурировать вызов следующим образом:

((IHTMLWindow2)webBrowserControl.Document.Window.DomWindow).execScript("var returnValue = someFunction([ 'abc', 'xyz', '1', '2', '3' ], { foo: 'xyz', bar: 1 });"

Обратите внимание, что мы используем .execScript, который делает все различия в мире. Это связано с тем, что вопреки .InvokeScript, который заставил бы javascript-метод использовать аргументы string (что заставляет вас использовать eval на стороне javascript),.execScript() дает нам возможность писать произвольные javascript, включая то, что вы видите выше (обратите внимание, что аргументы представляют собой явный массив javascript и мешок свойств). Теперь мы можем напрямую кодировать массивы и объекты и записывать их как аргументы. Для этого мы просто используем Newtonsoft.Json для сериализации массивов и объектов:

class Test {
     public string foo;
     public int bar;
}
((IHTMLWindow2)webBrowserControl.Document.Window.DomWindow).execScript("var returnValue = someFunction(" +
JsonConvert.SerializeObject((new List<object>(2) { "abc", "xyz", 1, 2, 3 }).ToArray()) + ", " + JsonConvert.SerializeObject(new Test() { foo = "xyz", bar = 1 }) + ");");

Другое дело - получить возвращаемое возвращаемое значение:

string result = (string)webBrowserControl.Document.InvokeScript("eval", new object[] { @"returnValue;" }));

Для вашего удобства вы можете написать метод утилиты, который выполняет итерацию по заданным параметрам и упорядочивает их правильно, вызывает функцию, а затем возвращает возвращаемое значение.

Ответ 4

Сначала вам нужно преобразовать массив в массив JS, что бы выглядело так:

["John", "Bob", "Sue"] // literal array

Ниже приводятся два примера:

StringBuilder sb = new StringBuilder();
string[] stringArray = bar.ToArray<string>();

//Build the JS array.
sb.Append( "[");
for (int i = 0; i < stringArray.Length; i++)
{
    sb.AppendFormat( "'{0}', ", stringArray[i] );

}
sb.Append( "]");


// Now send the array to the JS function.
myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, sb.ToString() });

Вы также можете удалить трейлинг. Не забудьте импортировать соответствующие библиотеки для StringBuilder, которые, по моему мнению, являются System.Text.StringBuilder;

или используйте, например, два:

string[] stringArray = bar.ToArray<string>();

// or simpler to use string join.
string jsArray = "[" + String.Join( ",", stringArray ) + "]";
//
myWebBrowser.InvokeScript("myJsFunc", new object[] { foo.Text, jsArray });