``
我有一个 C# 类库项目 (.Net Framework 4.5),我在 VB6 中将其用作类型库 (.tlb)。
使用 非集合对象作为属性或返回的属性,一切都可以正常工作。
据我所知,在C#项目中不可能公开诸如
Product []
这样的用户类型对象的集合(数组/列表)并将其导出到tlb文件,但是Object []
我听说这是可以的。所以,我改变了:
Public List<Product> ListOfProducts( get; set; )
到
Object [] _productList;
public Object [] ListOfProducts
{
get
{
return _productList;
}
set
{
_productList = value;
}
}
我也尝试过:
public void SetListOfProducts(Object [] products)
{
_productList= products;
}
完成后,
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
我的课程:
[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; }
}
我尝试过但没有成功:
也就是说,有没有办法从 C# 到 COM 获取和设置对象数组(最好是产品类型数组),甚至使用 .Net 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; }
}
VB6 不理解使用 SetProducts 的
object[]
或 Product[]
参数创建的类型库。
您可以通过作为方法参数传递而不是使用属性来传输对象数组
//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)