我正在用C#(.Net 4.0)构建COM对象,以在经典的ASP网站中使用。现在,我想知道在组件和asp站点之间来回配置VB-Script数组(单个和多维)的正确方法是什么?代码示例将不胜感激。
VBScript只喜欢处理包含VARIANTS的SAFEARRAY。它喜欢在COM方法或属性的VARIANTS中传递这些参数。因此,您需要构造一个包含VARIANT类型的SAFEARRAY的VARIANT属性。下面的C#代码执行此操作。首先只使用一个简单的对象数组,然后显示我们可以将任何其他托管类型的数组转换为对象数组,这样编组代码将为我们将其转换为SAFEARRAY of VARIANTs。
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计数10类型:Variant()名称:Variant()01个1个2358132134一二三四五
不是太多的答案,而是一些其他信息:
这是使用VBScript在Classic ASP中消耗爱国者的答案的方法:
<%@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]);
%>
有点晚,但是如果将来有人需要它:
我设法将ArrayList
的Hashtables
传递给Classic ASP。似乎可以传递名称空间System.Collections
的类型,System.Collections.Generic
无法传递。
。cs文件:
using System;
using System.Runtime.InteropServices;
using System.Collections;
namespace Test
{
[ComVisible(true)]
[Guid("D3A3F3E7-F1A9-4E91-8D7B-D9E19CF38165")]
public interface iDemo
{
[return: MarshalAs(UnmanagedType.Struct, SafeArraySubType = VarEnum.VT_ARRAY)]
ArrayList DemoMethod();
}
[ProgId("Test.Demo")]
[ClassInterface(ClassInterfaceType.None)]
[Guid("F53257DD-9275-4D6C-A758-EFF6932FF8B2")]
[ComVisible(true)]
public class Demo : iDemo
{
[ComVisible(true)]
public ArrayList DemoMethod()
{
ArrayList Results = new ArrayList();
for (int i = 0; i < 5; i++)
{
Hashtable table = new Hashtable();
table.Add("Text", "Test"+i);
table.Add("Number", i);
Results.Add(table);
}
return Results;
}
}
}
。asp文件:
<%
set test = server.createObject("Test.Demo")
set results = test.DemoMethod()
response.write "Results: " & results.count & "<br><br>"
for each result in results
response.write result("Text") & "<br>"
response.write result("Number") & "<br><br>"
next
%>
输出:
Results: 5
Test0
0
Test1
1
Test2
2
Test3
3
Test4
4
这非常方便,因为您必须将大量数据从C#传递到Classic ASP(也应在VB Script中工作,但未经测试),因为您可以遍历具有任何属性的对象。也没有进行其他测试,因为我只需要将数据从C#传递到Classic ASP。