Обрабатывать события COM в C# используя Reflection - PullRequest
0 голосов
/ 16 марта 2020

У меня есть COM-объект с основным интерфейсом и интерфейсом событий (из файла IDL):

[
    uuid(<interfaceId>,
    helpstring("AxBitViewerWidget Interface")
]
dispinterface IAxBitViewerWidget
{
    ...
};

[
    uuid(<eventsId>),
    helpstring("AxBitViewerWidget Events Interface")
]
dispinterface IAxBitViewerWidgetEvents
{
    ...
};

[
    aggregatable,
    helpstring("AxBitViewerWidget Class"),
    uuid(<mainClassId>), 
    control
]
coclass AxBitViewerWidget
{
    [default] dispinterface IAxBitViewerWidget;
    [default, source] dispinterface IAxBitViewerWidgetEvents;
};

Он был автоматически создан Active Qt. Затем в C# (в другой dll) я хочу подключиться к этому COM-объекту и обработать его события. Класс C# унаследован от AxHost. Все COM-типы являются динамическими c в моем примере и используются через Reflection. Вот фрагмент:

public class BitViewerEx : AxHost
{
    public BitViewerEx()
      : base(<mainClassId>)
    {
    }

    private void Initialize()
    {
        try
        {
            object ocx = GetOcx();
            if (ocx != null)
            {
                Type ocxType = ocx.GetType();
                Guid eventsGuid = new Guid(<eventsId>);
                Type eventsType = Type.GetTypeFromCLSID(eventsGuid);                
                var sinkEventsInterfaceObj = CreateInstanceCore(eventsGuid);

                // runtime error here
                var cookie = new ConnectionPointCookie(ocx, sinkEventsInterfaceObj, eventsType);
            }
        }
        catch (Exception ex)
        {
            System.Diagnostics.Trace.WriteLine(ex.ToString());
        }
    }
}

При вызове ConnectionPointCook ie из вышеперечисленного - возникает ошибка (приблизительно переведенная из локализованного сообщения): «Невозможно выполнить Advise () для интерфейса событий« __ComObject »».

Мой код правильный? Как правильно подключить AxBase к событиям COM-объекта? (для случая типов Dynami c нельзя использовать IAxBitViewerWidgetEvents и т. д. c. в C# коде)

PS: методы класса (не события) вызываются без проблем, например:

ocx.GetType().InvokeMember("initialize", System.Reflection.BindingFlags.InvokeMethod,
                                                null, ocx, new object[] { this.argum1, this.argum2 });

PS2: следующий код возвращает пустой массив:

System.Reflection.EventInfo[] arr = ocx.GetType().GetEvents();

1 Ответ

0 голосов
/ 17 марта 2020

Наконец-то я все заработал. Основной класс наследуется так:

public class BitViewerEx : AxHost, IBitViewerEvents

, где IBitViewerEvents (в зависимости от содержимого соответствующего автоматически сгенерированного файла .idl)

// Methods should be like signals in the Qt active-x class with the bit viewer.
// DispIds are taken from the .idl file for the corresponding methods.
[ComImport, Guid(<eventsId>)]
public interface IBitViewerEvents
{
    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(8)]
    void started();

    [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime), DispId(9)]
    void stopped();
}

Затем код подключения для все события упрощены до:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

...

private void Initialize() // BitViewerEx class member
{
    try
    {
        object ocx = GetOcx();
        if (ocx != null)
        {
            ocx.GetType().InvokeMember("initialize", System.Reflection.BindingFlags.InvokeMethod,
                                    null, ocx, new object[] { this.deviceAddress, this.cellAddress });

            var cookie = new ConnectionPointCookie(ocx, this, typeof(IBitViewerEvents));
        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Trace.WriteLine(ex.ToString());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...