1
votes

I am recently working with one type library requirement. I have created a c# class that will be exposed to COM component. However, when I set a value to an array property I get a compiler error. All the code are placed here.

Looking forward to your expert comments!

(VBA) Compile error:
Function or interface marked as restricted, or the function uses an Automation type not supported in Visual Basic

C# Com Class

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(_LeafletTestClass))]
[ProgId("Leaflet.WebService.Toolkit.LeafletWS.LeafletTestClass")]
[Guid("364C5E66-4412-48E3-8BD8-7B2BF09E8922")]
public class LeafletTestClass : _LeafletTestClass
{
    [ComVisible(true)]
    public string[] TestArrayString
    {
        [return: MarshalAs(UnmanagedType.SafeArray)]
        get;
        [param: MarshalAs(UnmanagedType.SafeArray)]
        set;
    }

}

[ComVisible(true)]
[Guid("8C034F6A-1D3F-4DB8-BC99-B73873D8C297")]
public interface _LeafletTestClass
{
    [ComVisible(true)]
    string[] TestArrayString
    {
        get;
        set;
    }
}

VBA Create Object

Sub test()

Dim testClass As LeafletTestClass
Set testClass = New LeafletTestClass
Dim arr(0 To 1) As String
arr(0) = "Test value"
testClass.TestArrayString = arr

End Sub
1
I am getting a compiler error. - Nitheen Rao
Sorry I completely missed it in your post, it looked like a code block - Mathieu Guindon
Why are you using ClassInterfaceType.None? Any particular reason? - cyboashu
Reg free COM or not, it's still good principle to ensure that you are not generating junk metadata. Yes, it's nice that COM interop helps you out, but it can only help naively; taking control ensures that it won't suddenly behave in a weird way when your implementation changes and thus trip up the assumptions the COM interop makes about your COM interfaces. - this

1 Answers

3
votes

I would recommend that you avoid using arrays. While you can use Marshal and possibly marshal it across it is fraught with issues due to difference in how empty arrays and nulls are handled, etc. etc.

To avoid runtime errors, you are better off writing a collection class and marshaling that across so that VBA can then simply enumerate. For an example of this, see here

At minimum your collection interface need to look like this:

[
    ComVisible(true),
    Guid(<some guid>),
    InterfaceType(ComInterfaceType.InterfaceIsDual)
]
public interface IDeclarations : IEnumerable
{
    [DispId(0)]
    Declaration Item(int Index);

    [DispId(1)]
    int Count { get; }

    [DispId(-4)]
    IEnumerator _GetEnumerator();
 }