PonWer
PonWer

Reputation: 87

COM Object Arrays From VB

I'm developing a COM Object in C#, Visual studio 2010, .NET 3.5, x86 which I'm using it in a VBA program.

namespace Test
{
    [Guid("8b65089f-5d98-41e7-9579-1ee384948e4c")]
    [ComVisible(true)]
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct Contact
    {
        [MarshalAs(UnmanagedType.BStr)] 
        public string Test1;
        public string[] Array;
    }


    [Guid("8b65082f-5d98-41e7-9579-1ee384948e4e"), ComVisible(true)]
    public interface IInContainer
    {
        Contact[] Contacts { [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] get; set; }
        string[] strings { [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_VARIANT)] get; set; }

    }

    [Guid("8b65089f-5d98-41e7-9579-1ee384948e4b"), ClassInterface(ClassInterfaceType.AutoDual), ComVisible(true)]
    public class InContainer
    {
        //[MarshalAs(UnmanagedType.BStr)]
        public Contact[] Contacts { get;set;}
        public string[] strings { get; set; }
    }

}

I'm able to see the structure/interface of the object in VB when I create it.

I can change the information in Container.strings from VB without any issue.

However, I cannot change the information in the Contact array (with the Contact structs) via VB.

Lets say the Contact array i 1 long, that node have all values set to "test". When trying to change it via VB i.e. Container.Contact(0).Test1 = "Monkey" I get no error. When trying to read it directly after i.e. Print(Container.Contact(0).Test1) I get "", or whatever default string I set.

I'm able to change the information in a contact by using a method on the container object, this is undesirable however.

So I need help why the values are read only in Container.Contact array.

Upvotes: 2

Views: 227

Answers (1)

Dirk Vollmar
Dirk Vollmar

Reputation: 176259

You are basically editing a copy of the struct, which is directly discarded after your assignment (because it is not kept in a variable).

If you decompose what Container.Contact(0).Test1 = "Monkey" does you get the following:

  • A copy of the Contact item at index 0 is created (because structs are value types)
  • The property Test1 is assigned the value "Monkey" on the copy of the contact
  • The copy of the contact struct with the modified Test1 property is discarded
  • When calling Print(Container.Contact(0).Test1) the original Contact struct still in the array is copied again, and the Test1 property of this newly created copy is printed.

One solution is to change your Contact type from struct to class1, or to replace the entire struct at the specified array index instead of trying to change just a single property or field.

dim cntct as Contact
cntct = Container.Contact(0)
cntct.Test1 = "Monkey"
Container.Contact(0) = cntct

1 Unless you are certainly sure that a struct is required here you probably want to change from struct to class.

Upvotes: 2

Related Questions