如何获得LINQPad到Dump()System .__ ComObject引用? [英] How to get LINQPad to Dump() System.__ComObject references?

查看:187
本文介绍了如何获得LINQPad到Dump()System .__ ComObject引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用说明了为什么发生,我认为我理解,但想知道什么选项有解决这个行为,特别是在使LINQPad(甚至)更强大的上下文中。



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





Visual Studio使用什么机制来实现这种自省,为什么LINQPad dump方法做同样吗? 修改:查看有关VS如何执行此操作的相关问题: Visual Studio的调试器/交互式窗口如何转储属性.NET中的COM对象?



ArcObjects .NET SDK 包括具有RCW的PAs,每个CoClass一个COM接口可以实现,所以我认为应该可以通过编程方式包装这些对象。 p>

作为解决方法我已成功使用 Marshal.CreateWrapperOfType() 在我的LINQ查询强制LINQPad转储对象的属性,知道应该使用哪个CoClass。当然,这只适当地转储值类型属性 - 任何基于COM的引用类型属性仍然报告为 System .__ ComObject ,因此一个合适的解决方案将不得不递归工作



上一个问题中获知CoClass可以在运行时确定它是否实现 IPersist ,这是ArcObjects的很大一部分。我可以用某种方式使用这种技术,或另一个,自动强制从一个 System .__ ComObject 到相应的RCW从PIA?如果是这样,我如何实现这在LINQPad,例如。通过提供 ICustomMemberProvider 实施?



我使用的目标是.NET 4.0的LINQPad 4.x,但是这样做是可以递归的,我也有兴趣支持LINQPad 2.x(所以解决方案,工作在.NET 3.5和.NET 4.0将是首选,但这不是一个要求)。



Update:我想出了我的问题的第一部分,它是如何在其RCW中包装 System .__ ComObject 使用返回的CLSID IPersist.GetClassID 。请参阅此相关问题此回答我正在使用的代码。



我仍然想知道如何使用LINQPad的Dump方法。

解决方案

我一直有一些相同的问题(除了我使用iTunes COM库)。



在visual studio中你并没有意识到,但是每个调试窗口都要求COM库在打开它时创建类型。这是不同于Dump(),这是,很好,不是互动。



我发现的唯一解决方案是,如果我知道什么类型的列表是做一个 OfType<>()强制转换为该类型。这将迭代列表并强制COM创建元素。



在上面的例子中,你会说:

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

NB - 您的毫米可能会有所不同, >

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

根据COM你可能需要把这个到下一步,并从那里拉出成员(使用com你必须要求得到的值)这样:

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

当然,如果有一个神奇的方式来做到这一点, t相信有因为COM的性质。


I am playing around with using LINQPad to rapidly develop small ArcObjects (a COM-based library for ESRI's ArcGIS software) applications and have had some success in using it to Dump() the properties of COM objects that I initialize from .NET, but any COM objects that are obtained from an existing COM object are simply dumped as System.__ComObject references, which is not particularly useful:

This help topic explains why this is happening, which I think I understand, but would like to know what options there are for working around this behavior, especially in the context of making LINQPad (even) more powerful.

Interestingly, Visual Studio's debugger is able to display the properties of these objects, and even values for value types:

What mechanism does Visual Studio use to achieve this introspection, and why doesn't LINQPad's Dump method do the same? Edit: See related question about how VS does this: How does Visual Studio's debugger/interactive window dump the properties of COM Objects in .NET?

The ArcObjects .NET SDK includes PIAs with RCWs for each CoClass a COM interface may be implemented by, so I'm thinking it should be possible to wrap these objects programmatically.

As a workaround I have successfully used Marshal.CreateWrapperOfType() within my LINQ queries to coerce LINQPad to dump the properties of the object when I happen to know which CoClass should be used. Of course, this only properly dumps value type properties -- any COM-based reference type properties are still reported as System.__ComObject, so a proper solution would have to work recursively to get those wrapped as well.

In a previous question I learned that the CoClass can be determined at runtime if it implements IPersist, which a good portion of ArcObjects do. Can I somehow use this technique, or another one, to automatically coerce a System.__ComObject to the appropriate RCW from the PIAs? And if so, how can I implement this in LINQPad, e.g. by providing an ICustomMemberProvider implementation? Can this be made to be recursive, so that properties that are also COM objects be wrapped as well?

I am using LINQPad 4.x which targets .NET 4.0, but am also interested in supporting LINQPad 2.x (so solutions that work on both .NET 3.5 and .NET 4.0 would be preferred, but that's not a requirement).

Update: I've figured out the first part of my question which was how to wrap a System.__ComObject in its RCW using the CLSID returned by IPersist.GetClassID. See this related question and this answer for the code I'm using.

I would still like to know how I can work this into LINQPad's Dump method.

解决方案

I've been having some of the same issues (except I'm working with iTunes COM library).

In visual studio you don't realize it but each debug window is asking the COM library to create the type when you open it. This is different than Dump() which is, well, not interactive.

The only solution I've found is if I know what type the list is to do a OfType<>() cast to that type. This will iterate over the list and force COM to create the elements.

So in your example above you would say:

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

NB - Your millage may vary, it turns out for the OP example this was needed.

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

Depending on the COM you might have to take this to the next step and pull out the members from there (with com you have to ask to get the value) something like this:

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

Sure would be nice if there was a "magical" way to make this happen, but I don't believe there is because of the nature of COM.

这篇关于如何获得LINQPad到Dump()System .__ ComObject引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆