Как правильно упорядочить массивы VB-Script в и из COM-компонента, написанного на C # - PullRequest
14 голосов
/ 22 февраля 2011

Я строю COM-объект в C # (.Net 4.0) для использования на классическом ASP-сайте. Теперь я хотел бы знать, как правильно маршалировать массивы VB-Script (одно- и многомерные) назад и вперед между компонентом и сайтом asp? Пример кода будет высоко оценен.

Ответы [ 2 ]

18 голосов
/ 24 февраля 2011

VBScript любит работать только с SAFEARRAY, которые содержат VARIANTS.И ему нравится, когда они передаются в VARIANTS для методов или свойств COM.Таким образом, вам нужно создать свойство VARIANT, которое содержит тип SAFEARRAY типа VARIANT.Следующий код C # делает это.Сначала используя простой массив объектов, а затем также показывая, что мы можем преобразовать массив любого другого управляемого типа в массив объектов таким образом, чтобы код маршаллинга преобразовал это в SAFEARRAY из VARIANT для нас.

using System;
using System.Runtime.InteropServices;
using System.Linq;

namespace StackOverflow
{
    [ComVisible(true)]
    [Guid("2F4C19A6-9BB9-4ACF-90D1-BAF48696740A")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IMyArrayDemo
    {
        [DispId(1)]
        int Count
        {
            [return: MarshalAs(UnmanagedType.I4)]
            get;
        }
        [DispId(2)]
        object Data
        {
            [return: MarshalAs(UnmanagedType.Struct, SafeArraySubType = VarEnum.VT_ARRAY)]
            get;
        }
        [DispId(3)]
        object Names
        {
            [return: MarshalAs(UnmanagedType.Struct, SafeArraySubType = VarEnum.VT_ARRAY)]
            get;
        }
    }

    [ComVisible(true)]
    [Guid("7EF75834-22BE-4861-879B-EA0CE20E46E9")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("StackOverflow.MyArrayDemo")]
    public class MyArrayDemo : IMyArrayDemo
    {
        object[] mData = new object[10] { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 };
        string[] mNames = new string[5] {"one", "two", "three", "four", "five"};
        public int Count { get { return mData.Length; } }
        public object Data { get { return mData; } }
        public object Names { get { return mNames.Cast<object>().ToArray(); } }
    }
}

Это можно проверить с помощью следующего vbscript:

Option Explicit
Sub Main
  Dim o, v
  Set o = CreateObject("StackOverflow.MyArrayDemo")
  WScript.Echo "Count " & o.Count & " type: " & TypeName(o.Data) & " names: " & TypeName(o.Names)
  For Each v in o.Data : WScript.Echo CStr(v) : Next
  For Each v in o.Names : WScript.Echo v : Next
End Sub
Main

Вы можете увидеть тип, указанный здесь как Variant (), то есть: массив вариантов.

C:\Users\pat>\windows\SysWOW64\cscript.exe -nologo arraytest.vbs
Count 10 type: Variant() names: Variant()
0
1
1
2
3
5
8
13
21
34
one
two
three
four
five
2 голосов
/ 02 августа 2012

Не столько ответ, сколько некоторая дополнительная информация:

Вот как использовать ответ Паттоайта в Classic ASP с использованием VBScript:

<%@Language=VBScript%>
<%
  Dim o, v
  Set o = CreateObject("StackOverflow.MyArrayDemo")
  Response.Write "Count " & o.Count & " type: " & TypeName(o.Data) & " names: " & TypeName(o.Names)
  For Each v in o.Data
    Response.Write "<br />" & v
  Next
  For Each v in o.Names
    Response.Write "<br />" & v
  Next
%>

Я не могу получить доступ к отдельным элементам массива (например, o.Names (2)), который указывает, что это не массив, а действует больше как коллекция.

Версия JScript:

<%@Language=JScript%>
<%
  var o, v;
  o = Server.CreateObject("StackOverflow.MyArrayDemo")
  Response.Write ("Count " + o.Count + " type: " + (typeof o.Data) + " names: " + (typeof o.Names));

  var a = o.Data.toArray();
  for (v=0; v<a.length; v++)
    Response.Write ("<br />" + a[v]);

  var b = o.Names.toArray();
  for (v=0; v<b.length; v++)
    Response.Write ("<br />" + b[v]);
%>
...