Loading and Passing JScript Arrays from/to C# (not

2019-03-03 01:51发布

问题:

I have looked at tutorials on jscript arrays, but not seeing it yet. I saw something similar asked but involving Win32 code not .NET.

Wondering, how do I pass arrays back and forth between JScript and a C# COM component?

For example, I have two properties defined in my C# COM that returns string and integer arrays as:

string[] HeaderLines { get; set; }
int[] ImagePixels { get; set; }

In my test.js file:

...

var T = new ActiveXObject("Imager.Reader"); 
...    
var headerLines = T.HeaderLines;
WScript.StdOut.WriteLine("First HeaderLine:" + headerLines[0]);
var pixels = T.ImagePixels;
WScript.StdOut.WriteLine("First Pixel: " + pixels[0]);

The error is where headerLines[0] is written out: C:\temp\test.js(12, 1) Microsoft JScript runtime error: 'headerLines.0' is null or not an object

If I remove the headerLines in test.js, then I get this error (essentially the same but for the integer array): C:\temp\test.js(12, 1) Microsoft JScript runtime error: 'pixels.0' is null or not an object

I can get results from non-array properties just fine as well as passing values to other methods, but not with arrays. I also need to pass in string and integer arrays into a method defined in my C# COM component as:

bool Write(string filename, string[] headerLines, int[] pix, int width, int height);

I am using Visual Studio Express 2012 for Desktop for creating the COM piece in C#. If any other information is needed, just let me know.

回答1:

Microsoft JScript engine implements JavaScript arrays as IDispatchEx objects. From C#, they can be manipulated via reflection or as dynamic objects (with dynamic, it's only possible to access properties and methods like length, push() etc., but not reference actual elements by their indices). Example:

JavaScript:

var T = new ActiveXObject("MySimulator.World"); 

var ar = ["a", "b", "c"];

T.MyFunction(ar);

C#:

public void MyFunction(object array)
{
    dynamic dynArray = array;
    int length = dynArray.length;
    dynArray.push("d");

    SetAt(array, 1, "bb"); 

    Console.WriteLine("MyFunction called, array.length: " + length);
    Console.WriteLine("array[0]: " + GetAt(array, 0));
    Console.WriteLine("array[1]: " + GetAt(array, 1));
    Console.WriteLine("array[3]: " + GetAt(array, 3));
}

static object GetAt(object array, int index)
{
    return array.GetType().InvokeMember(index.ToString(),
        System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetProperty,
        null, array, new object[] { });
}

static object SetAt(object array, int index, object value)
{
    return array.GetType().InvokeMember(index.ToString(),
        System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.SetProperty,
        null, array, new object[] { value });
}

Output:

MyFunction called, array.length: 3
array[0]: a
array[1]: bb
array[3]: d