2
votes

I have a relatively simple C#class that I would like to marshal into a VB project. It looks like this (I simplified a bit for this post):

[Guid("AAAAAAAA-AAAA-AAAA-AAAA-123456789ABC", ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
[ProgId("MyBiz.MyResponse")
[Serializable]

public class MyResponse
{
    public bool Success { get; set; }
    public int ID{ get; set; }
    public string Location{ get; set; }

    public ArrayList Messages { get; set; }
}

Messages contains 0 or more strings. I compile this and create a type library to be used by VB6. Everything work well in terms of data getting passed from the simple types, but the Messages variable, while the VB runtime recognizes it as an ArrayList, does not contain any data in it even when it should. What am I missing, in terms of marshaling the data? I know that generics do not marshal, but I believe an ArrayList does. Am I missing an attribute, or something else?

No need to offer alternative solutions, as I am asking this because I want to know how to do it, not because I don't have alternatives if I can get this to work. Thanks!

1
I can't believe VB 6 would recognize an arraylist, because it has no such functionality, unless you're referencing the .net framework from your VB6 program (which is possible but you didn't mention that). I know you said you weren't interested in alternatives, but if you want something VB6 can 'see' without .Net, try some other common ground (e.g, the Scripting library Dictionary object, or an array)FastAl
I'm not seeing that it does either. Here's a post that's going around: hightechtalks.com/dotnet-framework-interop/…BobRodes
I thought that I did this successfully before... something like the ArrayList gets written in IDL in your type library so VB6 knows its properties and then the call to Item to get the data is marshaled as either an object or a variant. If the data won't marshal right, write an IArrayList interface in .NET so you can specify the marshalling yourself with attributes.Mike
I was of the impression that while generics could not be marshaled, an ArrayList could - It's possible I'm wrong, though. @FastAi - I am not referencing the .NET framework from VB6. What I think is interesting is that it recognizes the ArrayList with the variable name of the arraylist in a watch window in VB6, it just doesn't have the values.Ev Conrad
There is no conceivable reason this won't work, you are not magically going to get an empty IList or IEnumerable from that ArrayList. If you don't know how to debug your C# code while a VB6 program is using it then ask an explicit question about that. Plenty of question marks on the class design, it is very rarely useful for client code to assign a new ArrayList. Drop the setter, make the property type IList or IEnumerable. Now you can use a List<string> in your code.Hans Passant

1 Answers

1
votes

One way to handle this is to use a COM SafeArray to pass data back and forth from .NET to COM. I have had better luck with this technique than with a ArrayList. The declaration for your Messages could look like:

[return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)]
public string[] Messages

This would be seen in VB6 or similar COM client as

Public Messages() as String

a COM SafeArray of Strings.