我在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); }
程序集使用强名称密钥进行签名,AssemblyInfo.cs具有[assembly:ComVisible(true)]属性集,但我不确定它与该问题有什么关系.
当我在VB6中查看对象浏览器时,我希望看到DoSomething(字符串)作为MyClass的成员,但我确实看到了每个公开方法都有匹配签名的事件,比如Event DoSomething (someParam As String)作为MyClass的成员.
更令人费解的是(至少对我而言),属性也有一个“匹配”事件(虽然只能从小闪电图标中看出) – 如果MyClass定义了这样的属性:
public string SomeProperty { get; set; }
VB6对象浏览器会说“事件”被定义为属性SomeProperty As String,这让我大吃一惊 – “属性”1)如何重复; 2)副本在对象浏览器中显示“事件”图标?这同样适用于只读属性,它们具有只读的“属性/事件”对应物.
这些事件来自哪里,如何摆脱它们?
更新图像胜过千言万语:
更新错误的是ComSourceInterfaces属性被错误地用于代替ComDefaultInterface属性.将前者换成后者会得到预期的结果:
解决方法
通过将typeof(IMyClass)作为参数传递给ComSourceInterface属性,您可以说IMyClass中的所有内容都是一个事件.
如果您不希望类的事件接口删除ComSourceInterface属性.
如果您确实要将C#类中的事件公开给VB,请执行以下操作:
当您创建COM可见类时,您还需要创建一个仅为您的类定义事件处理程序的接口.您的类应使用指定事件处理程序接口的COMSourceInterface进行修饰,并应定义事件并实现事件处理程序接口.有关其他示例,请参见How To: Raise Events Handled by a COM sink.
[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); } }