如何使用 C# 类型库 - COM-Interop 分配对象属性/方法数组?

Die*_*ron 5 c# vb6 com-interop

``

我有一个 C# 类库项目 (.Net Framework 4.5),我在 VB6 中将其用作类型库 (.tlb)。

对于将非集合对象作为属性或返回的属性,一切都可以正常工作。

据我所知,不可能公开用户类型对象的集合(数组/列表)(例如Product []在 C# 项目中)并将其导出到 tlb 文件,但Object []我听说这是可以的。所以,我改变了:

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

Run Code Online (Sandbox Code Playgroud)

Object [] _productList;
public Object [] ListOfProducts
{
    get
    {
        return _productList;
    }
    set
    {
        _productList = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

我也尝试过:

public void SetListOfProducts(Object [] products)
{
    _productList= products;
}
Run Code Online (Sandbox Code Playgroud)

完成后,ListOfProducts或者SetListOfProducts现在在 Visual Basic 6 项目中可见,但在 VB6 中,当我运行时:

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

Run Code Online (Sandbox Code Playgroud)

我的课程

[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;
  }
}
Run Code Online (Sandbox Code Playgroud)
[ClassInterface(ClassInterfaceType.AutoDual)]
[Guid("A4292449-4459-42D4-8FB0-18AA0D5FF34A")]
[ProgId("TlbProj.Product")]
[ComVisible(true)] 
public class Product
{
    public string EAN { get; set; }
}

Run Code Online (Sandbox Code Playgroud)

我尝试过但没有成功:

也就是说,有没有办法从 C# 到 COM 获取和设置对象数组(最好是产品类型数组),甚至使用 .Net 5+?谢谢你们!

Sim*_*ier 5

尽管 .NET 创建了有效的类型库,但 VB6 并不全部支持它们。.NET 泛型根本不能在边界处使用。

一种解决方案是使用ArrayList作为可在 C# 和 VB6 中使用的集合类型,但它是无类型的。它可以与 .NET Framework 一起使用,但不确定它是否仍然可以与 .NET Core3+ 一起使用(已注册?)。

这是一个有效的解决方案,并且针对读取列表进行了类型化,但对于写入操作来说是非类型化的:

[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; }
}
Run Code Online (Sandbox Code Playgroud)

VB6 不理解使用 SetProducts 创建的类型库object[]Product[]SetProducts 的参数。