COM服务器如何封送具有不同ComInterfaceType枚举的C#类库中可为null的值

本文关键字:类库 的值 null 枚举 ComInterfaceType 何封送 服务器 COM | 更新日期: 2023-09-27 18:26:40

我听说Nullable<T>是一个C#泛型类,它不能像任何其他泛型类一样使用COM。

嗯,在我的C#类库中,我有:

[InterfaceType(ComInterfaceType.InterfaceIsDual),
Guid("2FCEF713-CD2E-4ACB-A9CE-E57E7F51E72E")]
public interface ICOMClass
{
    int? GetNullable();
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("57BBEC44-C6E6-4E14-989A-B6DB7CF6FBEB")]
public class COMClass : ICOMClass
{
    public int? GetNullable()
    {
        int? hello = null;
        return hello;
    }
}

令人惊讶的是编译了它,并且我能够在VBE中附加对我的COMClass库的引用。

我知道:

  • VBA不会在对象浏览器的成员列表中列出.GetNullable()(即使勾选了"显示隐藏成员")
  • VBA不在智能意义下拉列表中列出.GetNullable()

但为什么:

Dim c as new COMClass
c.GetNullable

是否抛出了一个相当期望的Object doesn't support this property or method

与相反

c.NonExistingMethod

有人能解释为什么吗

我怀疑这与ComInterfaceType枚举有关,因为

  • 二者:InterfaceIsDual&InterfaceIsIDispatch的行为就像我上面描述的一样

但是:

  • InterfaceIsIUnknown实际上似乎没有封送/触摸GetNullable(),并且抛出了预期的错误

有人能解释这种行为吗?

COM服务器如何封送具有不同ComInterfaceType枚举的C#类库中可为null的值

好吧,它编译了。但你知道,当你试图为DLL创建一个类型库时,你会遇到麻烦:

C:'projects2'ClassLibrary38'bin'Debug>tlbexp ClassLibrary38.dll
Microsoft (R) .NET Framework Assembly to Type Library Converter 4.0.30319.33440
Copyright (C) Microsoft Corporation.  All rights reserved.
TlbExp : warning TX8013117D : Type library exporter warning processing 'ICOMClas
s.GetNullable(#0), ClassLibrary38'. Warning: Type library exporter encountered a
 generic type instance in a signature. Generic code may not be exported to COM.
Assembly exported to 'C:'projects2'ClassLibrary38'bin'Debug'ClassLibrary38.tlb'

您可以通过在类型库上运行OleView.exe来查看它。这就是你的界面:

[
  odl,
  uuid(2FCEF713-CD2E-4ACB-A9CE-E57E7F51E72E),
  version(1.0),
  dual,
  oleautomation,
  custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "ICOMClass")
]
interface ICOMClass : IDispatch {
};

没什么,娜达,齐波。Microsoft程序员在编写诊断消息时有时过于友好。这不仅仅是"可能不会",而是"不会"。

这是行不通的。它可以通过后期绑定找到方法也无济于事,返回值无法正确解释,Nullable<T>不是[ComVisible]。另一种选择是,考虑COM总是有"可为空性"的概念,VBA强烈支持这一概念,而VBA在很大程度上依赖于它。变量可以存储vtNull或vtEmpty,以指示未设置值。它是C#代码中的对象