2011-02-22 26 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]); 
%>