Выставление событий из .NET в COM - PullRequest
1 голос
/ 07 января 2009

Недавно у меня возникли проблемы с отображением событий из .NET в COM.

Я успешно справился с этим примером (концептуально взято из http://blogs.msdn.com/andreww/archive/2008/10/13/exposing-events-from-managed-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 (где я пытаюсь получить события), а также среда VBA, которую использует сторонний продукт (ESRI ArcMap).

Мне удалось (частично) реализовать интерфейс IConnectionPointContainer (который COM использует в фоновом режиме для обработки событий) вручную, затем я могу погрузить событие и войти в мою реализацию IConnectionPointContainer. Однако, это кажется мне излишним, и я думаю, что в .NET должна быть неявная поддержка этого. Во-вторых, при таком подходе я сразу теряю поддержку делегатов.

У кого-нибудь есть опыт с этим? Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 07 января 2009

Проще говоря, вы не сможете это сделать. Классический VB не поддерживает COM без автоматизации (как вы уже видели).

У вас должна быть обертка, которую вы можете передать своему экземпляру Automation, в котором будет публиковаться событие не-Automation. В действительности вам понадобится два отдельных типа для обработки двух отдельных клиентов для событий (с включенной автоматизацией и без автоматизации).

1 голос
/ 19 января 2009

Хорошо, так что я смог сделать это, реализовав классические COM IConnectionPointCointainer, IConnectionPoint и IConnection (плюс интерфейсы перечисления). Он не интегрируется в модель делегата / события .NET, но работает.

...