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

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

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

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

например,

alert(typeof theArray);

уведомления "неизвестный".

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

4 ответов


возможно, передайте его как строку 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


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

вот пример Функция JavaScript:

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

    // do stuff with stringArgs
}

и вы бы назвали это с C# так:

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

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

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

обратите внимание, что мы используем .execScript, который делает всю разницу в мире. Это потому, что противоречит .InvokeScript что бы forcefeed метод JavaScript с строка основанные аргументы (что заставляет вас использовать 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;" }));

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


сначала вам нужно преобразовать массив в массив 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, который я думаю, является система.Текст.То 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 });