问题
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.
回答1:
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).
回答2:
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.
来源:https://stackoverflow.com/questions/421467/exposing-events-from-net-to-com