Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a .NET class which holds a simple array of strings available via an accessor method, which looks like this;

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; }
        }
    }
}

I consume this class using 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 />"

This results in;

IsArray
String()
1

However, when I try to access the contents of the array using;

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

I get;

Microsoft VBScript runtime (0x800A01C2) Wrong number of arguments or invalid property assignment: 'MyArray'

Any help is much appreciated.

Edit This is to provide more information after digesting the answers given (thanks)

When changing the implementation of the MyArray property to;

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

I then get the following error,

Microsoft VBScript runtime (0x800A000D) Type mismatch: 'MyArray'

So I tried individually casting each string to an object;

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;
    }
}

Then I'm back to,

Microsoft VBScript runtime (0x800A01C2) Wrong number of arguments or invalid property assignment: 'MyArray'

Edit Final solution with help from 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)

The key was to expose object rather than object[] and as AnthonyWJones suggested, assign the array to a variable before using it.

Thanks again.

share|improve this question
    
This gave me the answer I was looking for. Just needed to add using System.Linq to make the cast work –  Graham Jun 26 '12 at 16:39

3 Answers 3

up vote 2 down vote accepted

The problem is VBScript cannot actually use an array of String. It can only use an array of Variant.

Try changing MyClass to expose an object[] instead.

share|improve this answer
    
Is there no way of casting it to an array of Variant? I only ask because clearly VBScript 'knows' it's an array, it 'knows' its current type, surely it knows how to cast it? I'd rather not change my .NET implementation just to keep legacy systems happy. –  Red Taz Oct 12 '11 at 8:23
    
@Rob2211: You could try assigning the property to VBScript variable and then use the variable. Thinking about it you might need to do that anyway but I still think you going to need to change the interface. It usually not a good idea to expose what you are actually using in a COM interface. Its better that you create a specific set of COM interfaces and classes that implement those interfaces. These classes then wrap and adapter your inner .NET classes. That way you build the COM interfaces in a way compatible with the consumer (VBScript) and yet not comprimise your .NET code –  AnthonyWJones Oct 12 '11 at 8:59
    
Thanks for the advice on writing a wrapper, I'll have to rewrite this later. Regardless, VBScript is still unhappy despite the fact the property now exposes object[] (see question edit) any thoughts? –  Red Taz Oct 12 '11 at 9:15
    
@Rob2211: Hmm.. sounds like you need to get explict. Another approach is to add the MarshalAs attribute to the property. Try specifying UnmanagedType.SafeArray as the unmanagedtype and set the SafeArraySubType property of the attribute to VarEnum.VT_VARIANT. –  AnthonyWJones Oct 12 '11 at 16:23

In addition to Anthony's suggestion

I'm not sure is it the best way but in the past I used a code similar to the following to handle one dimensional arrays.

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

In ASP:

Response.Write(TypeName(foo.MyArray)) 'string()
Response.Write(TypeName(foo.MyArray(0))) 'string
share|improve this answer

This code demonstrates how to handle arrays between COM and 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

%>

Here's a link to the article where I found this code:
http://202.102.233.250/b2000/ASP/articles/component/pv990826.htm

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.