【问题标题】:Retrieve string array from COM object using Classic ASP使用经典 ASP 从 COM 对象中检索字符串数组
【发布时间】:2011-12-05 11:56:39
【问题描述】:

我有一个 .NET 类,它包含一个简单的字符串数组,可通过访问器方法获得,如下所示;

namespace Foo.Bar {
    [ComVisible(true)]
    [Guid("642279A0-85D4-4c7a-AEF5-A9FAA4BE85E5")]
    public class MyClass {
        private string[] _myArray;
        public MyClass() { }

        public MyClass(string[] myArray) {
            _myArray = myArray;
        }

        public string[] MyArray {
            get { return _myArray; }
        }
    }
}

我使用 Classic ASP 使用这个类;

Dim foo 
Set foo = Server.CreateObject("Foo.Bar.MyClass")

if IsArray(foo.MyArray) then Response.Write("IsArray") & "<br />"
Response.Write(typename(foo.MyArray)) & "<br />"
Response.Write(UBound(foo.MyArray)) & "<br />"

这会导致;

IsArray
String()
1

但是,当我尝试使用;访问数组的内容时,

Response.Write(foo.MyArray(0)) & "<br />"

我明白了;

Microsoft VBScript 运行时 (0x800A01C2) 参数数量错误或 无效的属性分配:'MyArray'

非常感谢任何帮助。

编辑这是为了在消化给出的答案后提供更多信息(谢谢)

将 MyArray 属性的实现更改为;

public object[] MyArray {
    get { return (object[])_myArray; }
}

然后我得到以下错误,

Microsoft VBScript 运行时 (0x800A000D) 类型不匹配:'MyArray'

所以我尝试将每个字符串单独转换为一个对象;

public object[] MyArray {
    get {
        object[] tmp = new object[_myArray.Count()];
        for (int x = 0; x < _myArray.Count(); x++) {
            tmp[x] = (object)_myArray[x];
        }
        return tmp;
    }
}

那我又来了,

Microsoft VBScript 运行时 (0x800A01C2) 参数数量错误或 无效的属性分配:'MyArray'

编辑How to correctly marshal VB-Script arrays to and from a COM component written in C#的帮助下的最终解决方案

C#

public object MyArray {
    get { return _myArray.Cast<object>().ToArray(); }
}

VBScript

Dim foo 
Set foo = Server.CreateObject("Foo.Bar.MyClass")

bar = foo.MyArray
Response.Write bar(0)

关键是公开object 而不是object[],并且正如AnthonyWJones 建议的那样,在使用之前将数组分配给一个变量。

再次感谢。

【问题讨论】:

  • 这给了我想要的答案。只需使用 System.Linq 添加即可使演员工作

标签: asp.net com asp-classic


【解决方案1】:

问题是 VBScript 不能实际使用 String 的数组。它只能使用Variant 的数组。

尝试更改 MyClass 以改为公开 object[]

【讨论】:

  • 有没有办法将其转换为Variant 的数组?我只是问,因为显然 VBScript '知道'它是一个数组,它'知道'它的当前类型,它肯定知道如何转换它吗?我宁愿不要仅仅为了让遗留系统满意而改变我的 .NET 实现。
  • @Rob2211:您可以尝试将属性分配给 VBScript 变量,然后使用该变量。考虑一下,无论如何您可能都需要这样做,但我仍然认为您需要更改界面。在 COM 接口中公开您实际使用的内容通常不是一个好主意。最好创建一组特定的 COM 接口和实现这些接口的类。然后这些类包装和适配您的内部 .NET 类。这样,您就可以以与使用者 (VBScript) 兼容的方式构建 COM 接口,而且不会影响您的 .NET 代码
  • 感谢有关编写包装器的建议,我稍后将不得不重写。无论如何,VBScript 仍然不满意,尽管该属性现在公开了object[](请参阅问题编辑)有什么想法吗?
  • @Rob2211:嗯.. 听起来你需要明确一点。另一种方法是将MarshalAs 属性添加到属性。尝试将UnmanagedType.SafeArray 指定为非托管类型并将属性的SafeArraySubType 属性设置为VarEnum.VT_VARIANT
【解决方案2】:

除了 Anthony 的建议

我不确定这是不是最好的方法,但过去我使用类似于以下的代码来处理一维数组。

public object MyArray(int ix = -1){
    string[] tmp = new string[] {"one", "two", "3", "4"};
    return (ix == -1) ? (object)tmp : tmp[ix];
}

在 ASP 中:

Response.Write(TypeName(foo.MyArray)) 'string()
Response.Write(TypeName(foo.MyArray(0))) 'string

【讨论】:

    【解决方案3】:

    这段代码演示了如何在 COM 和 ASP 之间处理数组:

    <% @Language="VBScript" %>
    <% Option Explicit %>
    <%
    Dim tcs
    Dim rc
    Dim vntInput(0,4)
    Dim i
    
    vntInput(0,0) = Request.QueryString("strUser")
    vntInput(0,1) = Request.QueryString("intCreate")
    vntInput(0,2) = Request.QueryString("intDelete")
    vntInput(0,3) = Request.QueryString("intModify")
    vntInput(0,4) = Request.QueryString("intView") 
    
    Set tcs = Server.CreateObject("TestCases.ArrayFailure")
    rc = tcs.AcceptArray(vntInput)
    
    For i = 0 to UBound(vntInput, 2)
        Response.write "Loop Count " & i & " " & vntInput(0,i) & "<BR>"
    Next
    
    %>
    

    这是我找到此代码的文章的链接:
    http://202.102.233.250/b2000/ASP/articles/component/pv990826.htm

    【讨论】:

      猜你喜欢
      • 2010-11-14
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 2011-06-23
      • 1970-01-01
      • 2013-04-01
      • 2011-11-17
      • 1970-01-01
      相关资源
      最近更新 更多