You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# Native AoT:如何获取托管类指针传递给COM对象

解决方案:兼容Trim/Native AOT的COM事件接收器注册

在Trim和Native AOT场景下,无法依赖Marshal类的方法,需使用.NET原生支持的ComWrappers机制实现托管对象到COM IUnknown*的转换,进而完成IConnectionPoint::Advise的调用。以下是具体步骤和代码示例:

1. 确认接口与托管类的实现

确保CsWin32生成的INetworkListManagerEvents接口带有正确的COM特性(CsWin32生成COM接口时会自动添加[ComImport]、[Guid]等特性),同时你的托管类要正确实现该接口:

// CsWin32生成的INetworkListManagerEvents接口示例
[ComImport]
[Guid("DCB00C01-570F-4A9B-8D69-199FDBA5723B")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public partial interface INetworkListManagerEvents
{
    void NetworkListManagerConnectivityChanged(NLM_CONNECTIVITY newConnectivity);
}

// 自定义事件接收器类
public class NetworkEventsReceiver : INetworkListManagerEvents
{
    public void NetworkListManagerConnectivityChanged(NLM_CONNECTIVITY newConnectivity)
    {
        // 编写网络连接状态变化的处理逻辑
    }
}

2. 通过ComWrappers获取IUnknown指针

.NET 7及以上版本提供的ComWrappers.GetOrCreateComInterfaceForObject方法完全兼容Trim和Native AOT,可直接将托管对象转换为COM接口指针:

// 创建接收器实例
var receiver = new NetworkEventsReceiver();

// 获取IUnknown*对应的nint指针
nint unknownPtr = ComWrappers.GetOrCreateComInterfaceForObject(
    receiver,
    CreateComInterfaceFlags.None
);

// 将指针转换为CsWin32生成的IUnknown接口实例
IUnknown unknown = unsafe { MarshalInterface<IUnknown>.FromPointer((IUnknown*)unknownPtr); };

3. 调用IConnectionPoint::Advise完成注册

拿到IUnknown实例后,即可传入Advise方法,同时保存返回的cookie用于后续取消注册:

// 假设已通过INetworkListManager.FindConnectionPoint获取到IConnectionPoint实例
IConnectionPoint connectionPoint = ...;

uint cookie;
HRESULT hr = connectionPoint.Advise(unknown, &cookie);
if (hr.Succeeded)
{
    // 保存cookie,后续取消注册时调用connectionPoint.Unadvise(cookie)
}
else
{
    // 处理注册失败的逻辑
}

4. 通用场景适配

其他需要将托管类作为事件接收器传入Advise方法的场景,流程完全一致:

  • 确保托管类正确实现对应的COM事件接口
  • 使用ComWrappers.GetOrCreateComInterfaceForObject获取IUnknown指针
  • 将指针转换为目标COM接口类型后传入Advise

注意事项

  • 不再需要接收器时,务必调用IConnectionPoint::Unadvise并释放COM接口指针(可通过MarshalInterface<IUnknown>.Release或ComWrappers.ReleaseComInterface)
  • .NET 6及以下版本需自定义ComWrappers子类并手动注册,推荐升级到.NET 7+简化操作

内容的提问来源于stack exchange,提问作者Guezt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:52:37