c# - 如何获取 LINQPad 到 Dump() System.__ComObject 引用?

标签 c# com com-interop linqpad rcw

我正在尝试使用 LINQPad快速发展小ArcObjects (一个基于 COM 的库,用于 ESRI's ArcGIS 软件)应用程序,并在使用它来 Dump() 我从 .NET 初始化的 COM 对象的属性方面取得了一些成功,但任何 COM 对象都是从现有 COM 对象获取的对象被简单地转储为 System.__ComObject 引用,这不是特别有用:

LINQPad Screenshot

This help topic解释了为什么会发生这种情况,我想我理解,但想知道有哪些选项可以解决此问题,尤其是在使 LINQPad(甚至)更强大的情况下。

有趣的是,Visual Studio 的调试器能够显示这些对象的属性,甚至是值类型的值:

Visual Studio debugging ArcObjects

Visual Studio 使用什么机制来实现这种自省(introspection),为什么 LINQPad 的 Dump 方法不这样做? 编辑: 请参阅有关 VS 如何执行此操作的相关问题:How does Visual Studio's debugger/interactive window dump the properties of COM Objects in .NET?

ArcObjects .NET SDK包括 PIA 和每个 CoClass 的 RCW,一个 COM 接口(interface)可能由其实现,所以我认为应该可以通过编程方式包装这些对象。

作为解决方法,我已成功使用 Marshal.CreateWrapperOfType()在我碰巧知道应该使用哪个 CoClass 时,在我的 LINQ 查询中强制 LINQPad 转储对象的属性。当然,这只能正确转储值类型属性——任何基于 COM 的引用类型属性仍被报告为 System.__ComObject,因此正确的解决方案必须递归地工作以将这些属性也包装起来。

previous question 中我了解到,如果 CoClass 实现了 IPersist,则可以在运行时确定它。 ,这是 ArcObjects 的很大一部分。我能否以某种方式使用此技术或其他技术自动将 System.__ComObject 从 PIA 强制转换为适当的 RCW?如果是这样,我如何在 LINQPad 中实现它,例如通过提供 ICustomMemberProvider执行?是否可以使它成为递归的,以便同时包装也是 COM 对象的属性?

我正在使用以 .NET 4.0 为目标的 LINQPad 4.x,但我也有兴趣支持 LINQPad 2.x(因此可以在 .NET 3.5 和 .NET 4.0 上运行的解决方案是首选,但这不是必需的) .

更新:我已经弄清楚了问题的第一部分,即如何使用 返回的 CLSID 在其 RCW 中包装 System.__ComObject IPersist.GetClassID。看这个related questionthis answer对于我正在使用的代码。

我仍然想知道如何将其用于 LINQPad 的 Dump 方法。

最佳答案

我一直遇到一些相同的问题(除了我正在使用 iTunes COM 库)。

在 visual studio 中你没有意识到,但每个调试窗口在你打开它时都要求 COM 库创建类型。这与 Dump() 不同,后者是非交互式的。

我找到的唯一解决方案是,如果我知道列表是什么类型,就可以执行 OfType<>()转换为该类型。这将遍历列表并强制 COM 创建元素。

所以在你上面的例子中你会说:

var layers = map.EnumerateLayers("etc")
      .Select(s => s.OfType<Layer>())
      .Dump();

注意 - 您的 millage 可能会有所不同,事实证明这是 OP 示例所必需的。

var layers = map.EnumerateLayers()
      .OfType<IGeoFeatureLayer>()
      .Dump();

根据 COM,您可能必须将其带到下一步并从那里拉出成员(对于 com,您必须询问以获得值)如下所示:

var layers = map.EnumerateLayers("etc")
      .Select(x => x.OfType<Layer>())
      .Select(x => new { x.Depth, x.Dimention, }) // etc 
      .Dump();

如果有一种“神奇”的方式来实现这一点当然会很好,但我不相信这是因为 COM 的性质。

关于c# - 如何获取 LINQPad 到 Dump() System.__ComObject 引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14716871/

相关文章:

.net - 如何从 Visual Studio 2010 调试托管 BHO

c# - 读取嵌入式 XML 文件 C#

c# - 通用类型、集合和对象引用

com - 访问 COM 对象中的枚举 [jscript]

c++ - 从 ATL ActiveX 控件返回对象数组

c# - 互操作类作为泛型类型参数有什么问题?

c# - Csharp MySQL如何将变量插入查询

c# - 将数据与基本抽象类型的具体子类相关联

C# + COM,修改参数中的数组

c# - 如何使用 ActiveXObject 从 JavaScript 创建我的 C# Com 类