使COM互操作事件从接口可见

本文关键字:接口 事件 COM 互操作 | 更新日期: 2023-09-27 17:50:49

我写的代码像下面的例子:

public delegate void ClickDelegate(int x, int y);
public delegate void PulseDelegate();
[Guid("39D5B254-64DB-4130-9601-996D0B20D3E5"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
[ComVisible(true)]
public interface IButton
{
  void Work();
}
// Step 1: Defines an event sink interface (ButtonEvents) to be     
// implemented by the COM sink.
[GuidAttribute("1A585C4D-3371-48dc-AF8A-AFFECC1B0967") ]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public interface ButtonEvents
{
    void Click(int x, int y);
    void Pulse();
}
// Step 2: Connects the event sink interface to a class 
// by passing the namespace and event sink interface.
// ("EventSource.ButtonEvents, EventSrc").
[ComSourceInterfaces(typeof(ButtonEvents))]
public class Button : IButton
{
    public event ClickDelegate Click;
    public event PulseDelegate Pulse;
    public Button() { }
    public void CauseClickEvent(int x, int y) { Click(x, y); }
    public void CausePulse() { Pulse(); }
    public void Work() { /* Do some stuff */ }
}

这在VB中工作得很好。当我这样定义它时:

Dim WithEvents obj As Button

但是我想用这样的接口定义它:

Dim WithEvents obj As IButton

这是不工作的,因为事件是不可见的IButton接口。

有办法做到这一点吗?

使COM互操作事件从接口可见

连接到对象事件的变量必须声明为该对象(在您的示例中为Button)的类型(CoClass)。接口(在您的示例中是IButton)不知道任何关于事件的信息,因此不能使用它来请求它们。

我喜欢这样想:

接口是两个对象同意使用的东西,因此"客户端"可以向"服务器"发送命令("服务器,做XYZ!")。Event只是两个对象也同意使用的不同接口,但是用于相反的:即用于"服务器"对象向"客户端"发送命令。

是否支持给定的Event接口是对象的属性,而不是对象可能支持的任何接口的属性。服务器对象说:"给我一个ButtonEvents接口指针,我将用它来告诉你当按钮被点击"。这不是IButton接口提供的。

这也是为什么您必须将[ComSourceInterfaces]属性应用于类Button,而不是接口IButtonButton CoClass是提供报价的。

使事件看起来特别或奇怪的事情是,我们需要使用一个有点复杂和令人困惑的舞蹈("连接点")来传递事件的接口指针。WithEvents是让VB6为你"跳舞"的方式。