2011-02-22 24 views
13

我正在C#(.Net 4.0)中建立一个COM对象,用于传统的asp网站。现在我想知道在组件和asp网站之间来回传递VB-Script数组(单维和多维)的正确方法是什么?代码示例将受到高度赞赏。如何正确地编组VB和COM组件写入C#

回答

17

VBScript只喜欢处理包含VARIANTS的SAFEARRAY。它喜欢让这些通过VARIANTS在COM方法或属性上传播。所以你需要构造一个包含VARIANT类型的SAFEARRAY的VARIANT属性。以下C#代码执行此操作。首先只使用普通的对象数组,然后还显示我们可以将任何其他托管类型的数组转换为对象数组,以便编组代码将这些数据转换为VARIANT的SAFEARRAY。

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
+0

获取有关mNames.Cast线以下错误:“字符串[]”不包含“投射”的定义和没有扩展方法“投射”接受的第一个参数可以找到类型'string []'(你缺少using指令还是程序集引用?) – Graham

+0

System.Linq命名空间中提供了'Cast'方法,并在System.Core程序集中提供了该方法(请参见http:// msdn.microsoft.com/en-us/library/bb341406.aspx),所以默认项目应该有你需要的所有引用。我的项目副本有System,System.Core和Microsoft.CSharp的参考,没有别的。使用块如上所示。我用Visual Studio 2010构建了这个版本,但2008年应该也可以。 – patthoyts

+0

我的引用包括那三个,还有System.Xml.Linq等等。正在使用2010年。减少了仅仅那些3的参考,并且仍然存在错误。 – Graham

2

与其说是一个答案,但一些附加信息:

这是如何使用VBScript消耗patthoyts'在传统的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]); 
%>