将事件从 .NET 公开到 COM
最近,我在将事件从 .NET 暴露到 COM 时遇到了问题。
我已经成功地完成了这个示例(概念上取自http://blogs.msdn.com/andreww/archive/2008/10/13/exusing-events-from-management-add-in-objects.aspx):
// 我们的自定义事件的委托类型。
[ComVisible(false)]
public delegate void SomeEventHandler(object sender, EventArgs e);
// Outgoing (source/event) interface.
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IAddInEvents
{
[DispId(1)]
void SomeEvent(object sender, EventArgs e);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IAddInEvents))]
public class AddInUtilities :
{
// Event field. This is what a COM client will hook up
// their sink to.
public event SomeEventHandler SomeEvent;
inernal void FireEvent(object sender, EventArgs e)
{
if (SomeEvent != null)
{
SomeEvent(sender, e);
}
}
}
这工作正常,因为 IAddInEvents 接口被定义为 IDispatch。 但是,我需要发布一个 IUnknown 事件源接口。 我无法控制事件接口,因为它来自第三方库(它也将是已发布事件的使用者)。 每当我尝试挂钩事件时,VB 环境(我试图在其中接收事件)就会崩溃,第三方产品(ESRI ArcMap)使用的 VBA 环境也会崩溃。
我已经能够(部分)手动实现 IConnectionPointContainer 接口(COM 在后台使用该接口来处理事件),然后我能够接收事件并进入我的 IConnectionPointContainer 实现。 然而,这对我来说似乎有点矫枉过正,我认为 .NET 中必须对此有隐式支持。 其次,通过这种方法,我立即失去了代表的支持。
有人对这个有经验么? 提前致谢。
recently I have been encountering problems with exposing events from .NET to COM.
I have been successful with this example (conceptually taken from http://blogs.msdn.com/andreww/archive/2008/10/13/exposing-events-from-managed-add-in-objects.aspx):
// The delegate type for our custom event.
[ComVisible(false)]
public delegate void SomeEventHandler(object sender, EventArgs e);
// Outgoing (source/event) interface.
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IAddInEvents
{
[DispId(1)]
void SomeEvent(object sender, EventArgs e);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IAddInEvents))]
public class AddInUtilities :
{
// Event field. This is what a COM client will hook up
// their sink to.
public event SomeEventHandler SomeEvent;
inernal void FireEvent(object sender, EventArgs e)
{
if (SomeEvent != null)
{
SomeEvent(sender, e);
}
}
}
This works fine, because the IAddInEvents interface is defined as IDispatch. However, I need to publish an event source interface which is IUnknown. I do not have control over the event interface as it comes from a third-party library (which will also be the consumer of the published events). Whenever I try to hook to the events, VB environment (where I am trying to sink the events) crashes, so does the VBA environment which the third-party product (ESRI ArcMap) uses.
I have been able to (partially) implement IConnectionPointContainer interface (which COM uses in the background to handle events) manually, then I am able to sink the event and step into my IConnectionPointContainer implementation. However, this seems like an overkill to me and I think that there must an implicit support for this in .NET. Second, with this approach I instantly lose the delegate support.
Does anyone have any experience with this?
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
很简单,你将无法做到这一点。 经典 VB 不支持非自动化 COM(如您所见)。
您必须有一个包装器,您可以将自动化实例传递到该包装器,以公开非自动化事件。 实际上,您必须有两种单独的类型来处理事件的两个单独的客户端(启用自动化和未启用自动化)。
Quite simply, you won't be able to do this. Classic VB does not support non-Automation COM (as you have seen).
You will have to have a wrapper that you can pass your Automation instance to which will public the non-Automation event. You are effectively going to have to have two separate types to handle the two separate clients for the events (Automation-enabled and non-Automation enabled).
好的,我已经能够通过实现经典的 COM IConnectionPointCointainer、IConnectionPoint 和 IConnection(加上枚举接口)来实现这一点。 它没有集成到 .NET 委托/事件模型中,但可以工作。
Ok, so I have been able to this by implementing the classic COM IConnectionPointCointainer, IConnectionPoint and IConnection (plus the enumeration interfaces). It does not integrate into the .NET delegate/event model, but works.