繁体   English   中英

使用反射处理 C# 中的 COM 事件

[英]Handle COM events in C# using Reflection

我有一个带有主界面和事件界面的 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 类型都是动态的,并通过反射使用。 这是片段:

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());
        }
    }
}

从上面调用 ConnectionPointCookie 时 - 发生错误(大约从本地化消息转换而来):“无法为事件接口 '__ComObject' 执行 Advise()”。

我的代码正确吗? 如何正确地将 AxBase 连接到 COM 对象事件? (对于动态类型的情况,不能在 C# 代码中使用 IAxBitViewerWidgetEvents 等)

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();

最后我让它工作了。 主类是这样继承的

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());
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM