如何让LINQPad转到Dump()系统.__ ComObject引用?
我正在使用LINQPad来快速开发小型ArcObjects (一个基于COM的ESRI ArcGIS软件库)应用程序,并且已经成功地将它用于Dump()
我从.NET初始化的COM对象的属性,但是从现有COM对象获取的COM对象只是作为System.__ComObject
引用转储,这不是特别有用:
这个帮助主题解释了为什么会发生这种情况,我认为我理解,但是想知道解决这种行为有哪些选择,特别是在使LINQPad(甚至)更强大的环境中。
有趣的是,Visual Studio的调试器能够显示这些对象的属性,甚至是值类型的值:
Visual Studio使用什么机制来实现这种内省,为什么LINQPad的Dump方法不会这样做呢? 编辑:请参阅有关VS如何执行此操作的相关问题: Visual Studio的调试器/交互式窗口如何在.NET中转储COM对象的属性?
ArcObjects .NET SDK包含带有RCW的PIA,每个CoClass可以通过COM接口实现,所以我认为应该可以以编程方式包装这些对象。
作为一种解决方法,我在LINQ查询中成功使用Marshal.CreateWrapperOfType()
来强制LINQPad在我碰巧知道应该使用哪个CoClass时转储对象的属性。 当然,这只能正确转储值类型属性 – 任何基于COM的引用类型属性仍然报告为System.__ComObject
,因此正确的解决方案必须以递归方式工作以获取那些包装。
在之前的一个问题中,我了解到CoClass可以在运行时确定它是否实现了IPersist
,这是ArcObjects的很大一部分。 我可以以某种方式使用这种技术或其他技术自动将System.__ComObject
从PIA System.__ComObject
为适当的RCW吗? 如果是这样,我如何在LINQPad中实现它,例如通过提供ICustomMemberProvider
实现? 这可以是递归的,这样也可以包装也是COM对象的属性吗?
我正在使用面向.NET 4.0的LINQPad 4.x,但我也对支持LINQPad 2.x感兴趣(因此,首选适用于.NET 3.5和.NET 4.0的解决方案,但这不是必需的)。
更新:我已经弄清楚我的问题的第一部分是如何使用IPersist.GetClassID
返回的CLSID在其RCW中包装System.__ComObject
。 请参阅此相关问题和我正在使用的代码的答案 。
我仍然想知道如何将其用于LINQPad的Dump方法。
我一直有一些相同的问题(除了我正在使用iTunes COM库)。
在visual studio中你没有意识到它,但是每个调试窗口都要求COM库在你打开它时创建类型。 这与Dump()不同,Dump()不是交互式的。
我发现的唯一解决方案是,如果我知道该列表是什么类型的OfType<>()
强制转换为该类型。 这将迭代列表并强制COM创建元素。
所以在上面的例子中你会说:
var layers = map.EnumerateLayers("etc") .Select(s => s.OfType()) .Dump();
注意 – 你的millage可能会有所不同,事实certificate这是需要的OP示例。
var layers = map.EnumerateLayers() .OfType() .Dump();
根据COM的不同,您可能需要将其转到下一步并从那里拉出成员(使用com,您必须要求获取值),如下所示:
var layers = map.EnumerateLayers("etc") .Select(x => x.OfType()) .Select(x => new { x.Depth, x.Dimention, }) // etc .Dump();
如果有一种“神奇”的方法可以实现这一点,那肯定会很好,但我不相信因为COM的性质而存在。