C# 到 VB6 COM 事件(“对象或类不支持事件集”)

5

这个问题真的让我很头疼...

我有一个C#项目,其中定义了一个接口:

/* Externally Accessible API */
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ISerial
{
    [DispId(1)]
    bool Startup();

    [DispId(2)]
    bool Shutdown();

    [DispId(3)]
    bool UserInput_FloorButton(int floor_number);

    [DispId(4)]
    bool Initialize();
}

/* Externally Accesssible Event API */
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ISerialEvent
{
    [DispId(5)]
    void DataEvent();
}

[ComSourceInterfaces(typeof(ISerialEvent), typeof(ISerial))]
[ClassInterface(ClassInterfaceType.None)]
public class SerialIface : ISerial
{
    public delegate void DataEvent();
    public event DataEvent dEvent;

    public bool Initialize()
    {
        //testing the event callback
        if (dEvent != null)
        {
            dEvent();
        }
    }
    ...
}

VB6代码如下:

Private WithEvents objSerial As SerialIface

Private Sub objSerial_DataEvent()
    'do something happy'
End Sub

Public Sub Class_Initialize()
    Set objSerial = New SerialIface  '<---this is the line that fails'
    Call objSerial.Initialize  '<--Initialize would trigger DataEvent, if it got this far'
End Sub

嗯,普通的API函数似乎可以正常工作(如果我声明objSerial而不使用WithEvents关键字),但是我无论如何都无法让"DataEvent"起作用。它会提示"对象或类不支持事件集"的错误信息。

我最初将两个接口合并在一起,但是C#抱怨DataEvent未定义在类中。现在,我能够在VB6对象浏览器中查看所有API和一个完美的事件--所有东西看起来都在那里...我只是不能让它真正地工作!

我相信我正在错过一些显而易见的事情或者做了一些愚蠢的事情--但是我对整个互操作的业务还很陌生,所以完全逃避了我。

救命啊!


你是否尝试将对象声明为事件源接口之一,而不是类接口? - JP Alioto
我刚刚发现,如果我使用完全独立的类和接口——只有事件而没有实现的API,它就可以工作了。(此外,我可以从主类中调用这个单独的类来发送事件——但这相当笨拙。是否有任何方法可以在同一个类或接口中同时拥有事件和常规API?) - EMon
JP,感谢您的快速回复。"Private WithEvents objSerial As ISerialEvent" 会产生 "编译错误:对象不提供自动化事件" 的错误。 - EMon
2个回答

7
请查看这篇文章here
具体来说,你好像缺少一个声明,类似于这样。
[Guid("9E5E5FB2-219D-4ee7-AB27-E4DBED8E123E"),
    ClassInterface(ClassInterfaceType.None),
    ComSourceInterfaces(typeof(DBCOM_Events))]
    public class DBCOM_Class : DBCOM_Interface
    {

你有这部分
// // Events interface Database_COMObjectEvents 
[Guid("47C976E0-C208-4740-AC42-41212D3C34F0"), 
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface DBCOM_Events 
{
}

但是如果没有第二个,COM对象的虚表和类型库将没有事件映射,无法与VB6(或其他COM消费者)一起使用。

您可以使用Google搜索词“com event” c#并获得其他很好的结果。


感谢您的帖子和链接。嗯,我实际上认为我在上面已经有了那个。我把属性顺序搞反了,但我认为一切都在那里。不过我没有设置Guid - 我会尝试一下,但我在其他地方读到过这不是必要的(或者说会自动生成)。 - EMon

4

我使用委托而不是事件来定义接口:

/* Externally Accesssible Event API */
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ISerialEvent
{
    [DispId(5)]
    void DataEvent();
}

应该是

/* Externally Accesssible Event API */
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ISerialEvent
{
    [DispId(5)]
    void dEvent();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接