VB6/COM Interop:这些事件来自哪里?

Mat*_*don 6 c# vb6 com-interop

我在C#4.0中编写了一个COM可见的类库,我正在使用VB6.事情是有效的,只有当我打开VB6 对象浏览器并查看暴露的成员时,我才会看到每个暴露成员的事件...... 但是C#代码没有定义它们中的任何一个.

这是正常的吗?难道我做错了什么?

[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IMyClass))]
public class MyClass : IMyClass
{
    public void DoSomething(string someParam)
    {
        ...
    }
}

public interface IMyClass
{
    void DoSomething(string someParam);
}
Run Code Online (Sandbox Code Playgroud)

程序集使用强名称密钥签名并设置AssemblyInfo.cs[assembly: ComVisible(true)]属性,但我不确定它与问题有什么关系.

当我看到在VB6对象浏览器,我会期待看到DoSomething(string)其中的一名成员MyClass,和我做的,但是我看到具有匹配签名事件,每暴露方法,像Event DoSomething(someParam As String)其中的一名成员MyClass.

更令人费解的是(至少对我而言),属性也有一个"匹配"事件(虽然只能从小闪电图标中看出) - 如果MyClass定义了这样的属性:

public string SomeProperty { get; set; }
Run Code Online (Sandbox Code Playgroud)

VB6对象浏览器会将"事件"定义为Property SomeProperty As String,这让我大吃一惊 - "属性"1)如何重复; 2)副本是否在对象浏览器中显示"事件"图标?这同样适用于只读属性,它们具有只读的"属性/事件"对应物.

这些事件来自哪里,如何摆脱它们?

更新图像胜过千言万语:

COM Interop  - 伪造事件

UPDATE错误的事情ComSourceInterfaces这是错误地被代替的使用属性ComDefaultInterface的属性.将前者换成后者会得到预期的结果:

COM Interop  - 正确的成员

Dan*_*sha 8

通过将typeof(IMyClass)参数作为参数传递给ComSourceInterface属性,您会说IMyClass中的所有内容都是一个事件.

如果您不希望类的事件接口删除ComSourceInterface属性.

如果您确实要将C#类中的事件公开给VB,请执行以下操作:

当您创建COM可见类时,您还需要创建一个仅为您的类定义事件处理程序的接口.您的类应使用指定事件处理程序接口的COMSourceInterface进行修饰,并应定义事件并实现事件处理程序接口.有关其他示例,请参见如何:提升COM接收器处理的事件.

[GuidAttribute("1A585C4D-3371-48dc-AF8A-AFFECC1B0967") ]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
public interface MyEvents
{
    void ConnectedEvent(string state);
}


[ComSourceInterfaces(typeof(MyEvents))]
public class MyClass
{
    public event Action<string> ConnectedEvent;

    public MyClass() { }

    public void DoSomething(string state)
    { 
        if (ConnectedEvent != null)
            ConnectedEvent(state);
    }
}
Run Code Online (Sandbox Code Playgroud)

另见:Murat的角落:暴露COM事件

  • @retailcoder但是你用'ComSourceInterfaces`属性做了.这告诉tlbexport您的对象可以在给定该接口的情况下获取事件. (3认同)

Han*_*ant 8

您基本上发现COM中的事件没有任何特殊之处.与COM中的任何内容一样,事件由接口支持.对于指定事件方法的接口,唯一特别之处在于它在类型库中使用[source]属性进行标记.这就是[ComSourceInterfaces]属性所做的一切,Tlbexp.exe在生成类型库时会识别它.

COM中的属性也没有什么特别之处.它们就像在.NET中一样工作,它们是用方法实现的.一个getter和一个setter方法.

因此,VB6会查看您的类型库,并且对具有事件的类感到高兴,因为它具有[source]属性的接口.并且对于具有方法的接口感到高兴,他们可以拥有它们,因此它假定这些是在引发事件时运行的方法.知道那些方法也是属性的访问器是不够智能的,它假定类型库作者知道他在做什么.

事件在COM中称为"连接点".谷歌IConnectionPoint了解更多信息.如果您使用自定义事件访问器创建WinRT组件,那么您还将看到COM事件与.NET事件几乎没有共同之处.

Anyhoo,解决方法很简单,只在引发事件时使用[ComSourceInterface].