6

私はLINQPadを使用して小さなArcObjects ( ESRI の ArcGISソフトウェア用の COM ベースのライブラリ) アプリケーションを迅速に開発して遊んでおりDump()、.NET から初期化する COM オブジェクトのプロパティにそれを使用することに成功しましたが、既存の COM オブジェクトから取得されたものは、単にSystem.__ComObject参照としてダンプされるだけであり、特に有用ではありません。

LINQパッドのスクリーンショット

このヘルプ トピックでは、これが発生する理由を説明していますが、これは理解できたと思いますが、特に LINQPad (さらに) をより強力にするというコンテキストで、この動作を回避するためのオプションを知りたいです。

興味深いことに、Visual Studio のデバッガーは、これらのオブジェクトのプロパティを表示でき、値の型の値も表示できます。

Visual Studio の ArcObject のデバッグ

Visual Studio はこのイントロスペクションを実現するためにどのメカニズムを使用しますか? また、LINQPad の Dump メソッドが同じことを行わないのはなぜですか? 編集: VS がこれを行う方法に関する関連する質問を参照してください: Visual Studio のデバッガー/対話型ウィンドウは、.NET の COM オブジェクトのプロパティをどのようにダンプしますか?

ArcObjects .NET SDKには、COM インターフェイスを実装できる各 CoClass の RCW を備えた PIA が含まれているため、これらのオブジェクトをプログラムでラップできるはずだと考えています。

回避策としてMarshal.CreateWrapperOfType()、LINQ クエリ内で使用して、LINQPad に強制的にオブジェクトのプロパティをダンプさせることに成功しました。もちろん、これは値型プロパティのみを適切にダンプします。COM ベースの参照型プロパティは引き続き として報告されるSystem.__ComObjectため、適切な解決策として再帰的に動作し、それらをラップする必要があります。

以前の質問で、CoClass が を実装しているかどうかを実行時に決定できることを知りました。IPersistこれは、ArcObjects の大部分が行っています。この手法または別の手法を使用しSystem.__ComObjectて、PIA から適切な RCW に自動的に強制することはできますか? もしそうなら、ICustomMemberProvider実装を提供するなどして、LINQPadでこれを実装するにはどうすればよいですか? これを再帰的にして、COM オブジェクトでもあるプロパティもラップできるようにすることはできますか?

.NET 4.0 をターゲットとする LINQPad 4.x を使用していますが、LINQPad 2.x のサポートにも関心があります (.NET 3.5 と .NET 4.0 の両方で動作するソリューションが望ましいですが、必須ではありません)。

更新:System.__ComObjectによって返された CLSID を使用して RCW でa をラップする方法である私の質問の最初の部分を理解しましたIPersist.GetClassID。私が使用しているコードについては、この関連する質問この回答を参照してください。

これを LINQPad の Dump メソッドに組み込む方法を知りたいです。

4

1 に答える 1

0

私はいくつか同じ問題を抱えています (iTunes COM ライブラリを使用していることを除いて)。

Visual Studio では気付かないかもしれませんが、各デバッグ ウィンドウは、開くときに COM ライブラリに型を作成するように要求しています。これは、インタラクティブではない Dump() とは異なります。

私が見つけた唯一の解決策は、リストがOfType<>()その型にキャストする型を知っている場合です。これにより、リストが反復処理され、COM に要素が作成されます。

したがって、上記の例では、次のように言います。

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

NB - ミレージは異なる場合があります。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 の性質上、そうではないと思います。

于 2013-02-06T19:27:21.127 に答える