5

``

I have a C# class library project (.Net Framework 4.5) that I use it in VB6 as a type library (.tlb).

Everything works fine with properties with non-collection objects as attributes or returns.

As far as I know, it's not possible to expose a collection (Array/List) of a user-type object such as Product [] in a C# project and export it to tlb file, but Object [] I heard it's okay. So, I changed:

Public List<Product> ListOfProducts( get; set; )

to

Object [] _productList;
public Object [] ListOfProducts
{
    get
    {
        return _productList;
    }
    set
    {
        _productList = value;
    }
}

I also tried:

public void SetListOfProducts(Object [] products)
{
    _productList= products;
}

That done, ListOfProducts or SetListOfProducts now are visible in Visual Basic 6 project, but in VB6, when I run:

Private Sub Command1_Click()
    Dim Sell as new SellProducts
    Dim prodct(1) As New TlbProj.Product 'Product is a class inside of the tlb file
    prodct(0).EAN = "7894900011517"
    prodct(1).EAN = "7894900017011"
    
    Dim prodctVariant(1) As Variant
    'Set prodctVariant = prodct or prodctVariant = prodct  throws "Can't assign to array error"
    prodctVariant(0) = prodct(0)  'one by one was the only way I managed to do this. That's not the major problem.
    prodctVariant(1) = prodct(1)

    Sell.ListOfProducts = prodctVariant
    'The object browser shows: 'Property ListOfProducts As Variant()
    'it throws the message: "Function or interface marked as restricted, or the function uses an Automation type not supported in Visual Basic"

    Sell.SetListOfProducts prodctVariant
    'The object browser shows: 'Sub SetListOfProducts(products() As Variant)
    'it throws the message: "Function or interface marked as restricted, or the function uses an Automation type not supported in Visual Basic"

End Sub


My classes:

[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("757E6144-FC46-44A0-89DB-B89EF8F75BAB")]
[ProgId("TlbProj.SellProducts")]
[ComVisible(true)]
public Class SellProducts
{
  Object [] _productList;
  public Object [] ListOfProducts
  {
      get
      {
          return _productList;
      }
      set
      {
          _productList = value;
      }
  }

  public void SetListOfProducts(Object [] products)
  {
      _productList= products;
  }
}
[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("A4292449-4459-42D4-8FB0-18AA0D5FF34A")]
[ProgId("TlbProj.Product")]
[ComVisible(true)] 
public class Product
{
    public string EAN { get; set; }
}

I have tried with no success:

That said, is there a way to get and set Array of Object (preferably to Array of Product type) from C# to COM, even using .Net 5+? Thank you all!

2 Answers 2

5

Although .NET creates valid type libraries, they are not all supported by VB6. .NET generics cannot be used at all at boundaries.

One solution is to use ArrayList as a collection type usable in C# and VB6 but it's untyped. It works with .NET Framework, but not sure it still works (registered?) with .NET Core3+.

Here is a solution that works and is typed for reading the list, but is untyped for write operations:

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("757E6144-FC46-44A0-89DB-B89EF8F75BAB")]
[ProgId("TlbProj.SellProducts")]
public class SellProducts
{
    private readonly List<Product> _products = new List<Product>();

    public SellProducts()
    {
        _products.Add(new Product { EAN = ".NET1234" });
        _products.Add(new Product { EAN = ".NET5678" });
    }

    // read only mode
    public Product[] Products => _products.ToArray();

    // write mode, untyped :-(
    public void SetProducts(object products)
    {
        _products.Clear();
        if (products is IEnumerable enumerable)
        {
            _products.AddRange(enumerable.OfType<Product>());
        }
    }
}

[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("A4292449-4459-42D4-8FB0-18AA0D5FF34A")]
[ProgId("TlbProj.Product")]
[ComVisible(true)]
public class Product
{
    public string EAN { get; set; }
}

VB6 doesn't understand type libs created with object[] or Product[] parameters for SetProducts.

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

Comments

0

You can transfer an Array of Objects by passing as a method parameter instead of using properties

//C# .Net-Code
[ComVisible(true)]
[Guid("35CF1524-0F2E-4711-AF6D-3AEA8AD532D1")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("MyNameSpace.Product")]
public class Product 
{
    public string Name { get; set; }

    public Product() 
    { 
         Name = "";
    }
}


[ComVisible(true)]
[Guid("0057C7F6-0119-4DB1-8C16-153A2C6A97C9")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("MyNameSpace.TransferHandler")]
public class TransferHandler 
{
    List<Product> Products {get; set;}

    public TransferHandler()
    {
        Products = new List<Product>();
    }

    public void Send(ref Product[] products) 
    {
        Products = products.ToList()
    }
}

'VBA-Code
Dim products(1) As MyNameSpace.Product

Set products(0) = new MyNameSpace.Product
products(0).Name = "foo"
Set products(1) = new MyNameSpace.Product
products(1).Name = "bar"

Dim transferHandler As MyNameSpace.TransferHandler
Set transferHandler = new MyNameSpace.TransferHandler

Call transferHandler.Send(products)

1 Comment

may you add some more information on what your code does?

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.