【问题标题】:String Array property in COM Class and set it from VBACOM 类中的字符串数组属性并从 VBA 设置它
【发布时间】:2019-01-18 10:18:44
【问题描述】:

我最近正在处理一种类型库需求。我创建了一个将暴露给 COM 组件的 c# 类。但是,当我为数组属性设置值时,会出现编译器错误。所有的代码都放在这里。

期待各位高手!

(VBA) 编译错误:
函数或接口标记为受限,或函数使用 Visual Basic 不支持的自动化类型

C# Com 类

[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 创建对象

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

【问题讨论】:

  • 我收到编译器错误。
  • 对不起,我完全错过了你的帖子,它看起来像一个代码块
  • 你为什么使用ClassInterfaceType.None?有什么特别的原因吗?
  • Reg free COM 与否,确保您不会生成垃圾元数据仍然是一个很好的原则。是的,COM 互操作可以帮助您很好,但它只能天真地提供帮助;取得控制权可确保当您的实现发生变化时它不会突然出现奇怪的行为,从而打破 COM 互操作对您的 COM 接口所做的假设。

标签: c# vba com marshalling tlb


【解决方案1】:

我建议您避免使用数组。虽然您可以使用 Marshal 并可能将其编组,但由于处理空数组和空值的方式等不同,它充满了问题。

为避免运行时错误,您最好编写一个集合类并将其编组,以便 VBA 可以简单地枚举。例如,see here

您的收藏界面至少需要如下所示:

[
    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();
 }

【讨论】:

  • 我仍然不知道如何用 Array 替换它。
  • 您能否详细说明一下——您尝试了哪些方法,哪些方法不起作用?
猜你喜欢
  • 2011-08-26
  • 1970-01-01
  • 2016-07-06
  • 1970-01-01
  • 1970-01-01
  • 2020-10-28
  • 1970-01-01
  • 2023-03-17
  • 2016-12-20
相关资源
最近更新 更多