4

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.

1
  • This gave me the answer I was looking for. Just needed to add using System.Linq to make the cast work Commented Jun 26, 2012 at 16:39

4 Answers 4

3

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.

Sign up to request clarification or add additional context in comments.

4 Comments

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.
@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
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?
@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.
2

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

Comments

0

VBScript doesn't understand generic collections such as List<string> and it doesn't understand string arrays either.

I wrote a public function into my Interface class to convert any generic collections into an ArrayList

public ArrayList toArrayList(IEnumerable collection)
{
        var arrayList = new ArrayList();
        foreach (object element in collection)
        {
            arrayList.Add(element);
        }
        return arrayList;
}

This code can then be used in VBScript like this

 dim connector
 set connector = model.getRelationByID(connectorID)
 'get the related elements
 dim relatedElements
 set relatedElements = model.toArrayList(connector.relatedElements)
 addRelatedElementoAutoDiagram relatedElements(0), relatedElements(1), model

The advantage of this approach is that I don't need to change the signature of any of the methods or properties in C#, but I can still use them in VBScript

1 Comment

Nice wrapper that doesn't require signature changes.
-2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.