使用 COM 对象上的反射调用方法

Posted

技术标签:

【中文标题】使用 COM 对象上的反射调用方法【英文标题】:Invoke method using Reflection on COM Object 【发布时间】:2011-02-15 21:53:40 【问题描述】:

我有一个 COM 对象的实例......它是这样创建的:

Type type = TypeDelegator.GetTypeFromProgID("Broker.Application");
Object application = Activator.CreateInstance(type);

当我尝试调用一个方法时:

type.GetMethod("RefreshAll").Invoke(application, null);

-> type.GetMethod("RefreshAll") 返回null。 当我尝试使用type.GetMethods() 获取所有方法时,只有这些方法:

    GetLifetimeService 初始化LifetimeService CreateObjRef ToString 等于 GetHashCode 获取类型

RefreshAll 方法在哪里?我该如何调用它?

【问题讨论】:

【参考方案1】:

你不能在 COM 对象上使用 GetMethod,你必须使用不同的 方式:

this.application.GetType().InvokeMember("RefreshAll", BindingFlags.InvokeMethod, null, this.application, null);

我在一个使用 COM 的旧项目中使用这种方式,所以它应该适合你。

【讨论】:

虽然在当时是一个很好的答案,但 c# 4 通过下面的 dynamic 关键字可以更轻松地执行 COM 互操作 注意,由于在我的工具github.com/awaescher/RepoZ 中使用dynamic,我发现它存在严重的内存泄漏。我切换到 Nathan W 的答案来解决这个问题!在此处查看更多信息:***.com/questions/33080252/… 在 MickyD 上查看其他 cmets 关于如何处理该问题的答案 ...【参考方案2】:

我意识到这是一个较晚的答案,但 c# 4 引入了 dynamic 关键字,该关键字在设计时考虑了 COM-interop。

MSDN:

C# 团队在 C# 4 版本中专门针对的 COM 互操作方案是针对 Microsoft Office 应用程序(例如 Word 和 Excel)进行编程。其目的是让 C# 中的这项任务像在 Visual Basic 中一样简单自然。 [1]

您的代码现在变为:

Type type = TypeDelegator.GetTypeFromProgID("Broker.Application");
dynamic application = Activator.CreateInstance(type);
application.RefreshAll(); // <---- new in c# 4

现在您不会在 Visual Studio 语句完成中看到 RefreshAll(),所以不要惊慌。它会编译。

[1]Understanding the Dynamic Keyword in C# 4

【讨论】:

注意,由于在我的工具github.com/awaescher/RepoZ 中使用dynamic,我发现它存在严重的内存泄漏。我切换到 Nathan W 的答案来解决这个问题!在此处查看更多信息:***.com/questions/33080252/… @Waescher 很奇怪,考虑到 MS 首先是为 COM 设计的。我怀疑你只是没有正确发布与 dynamic 无关的东西 @Waescher 哦,我刚刚做了一些谷歌搜索,看来你是对的。讨厌的小动态。很好的发现 感谢指正。我发布的那个链接 (***.com/questions/33080252/…) 显示了我所面临的问题以及所有 RuntimeBinder 的问题。不要误会,泄漏是巨大的:i.imgur.com/5ucIcI6.png。我可能会补充一点,我经常调用包含dynamic 的方法,但无论如何...... @Waescher 不,谢谢-。我想我没有在我的东西中注意到它,因为应用程序不会运行很长时间然后退出。希望MS能改正。 :)

以上是关于使用 COM 对象上的反射调用方法的主要内容,如果未能解决你的问题,请参考以下文章

使用反射的方法调用的问题问题,怎么解决

Java反射调用与面向对象结合使用产生的惊艳

反射生成对象,调用对象方法

跟王老师学反射:使用反射调用方法

如何使用 C# 中的反射调用将输入参数作为另一个类对象的方法?(方法给出参数异常)

java反射调用方法可以传非基本类型吗?如对象、接口