Как получить LINQPad для Dump() System.__ComObject ссылки?

Я играю с использованием LINQPad для быстрой разработки небольших приложений ArcObjects (библиотека на основе COM для программного обеспечения ESRI ArcGIS) и добился определенного успеха в его использовании для Dump() свойства COM-объектов, которые я инициализирую из.NET, но любые COM-объекты, полученные из существующего COM-объекта, просто выводятся как System.__ComObject ссылки, которые не особенно полезны:

Скриншот LINQPad

Этот раздел справки объясняет, почему это происходит, что, я думаю, я понимаю, но хотел бы знать, какие есть варианты для обхода этого поведения, особенно в контексте повышения производительности LINQPad (даже).

Интересно, что отладчик Visual Studio способен отображать свойства этих объектов и даже значения для типов значений:

Visual Studio, отладка ArcObjects

Какой механизм использует Visual Studio для достижения этого самоанализа, и почему метод дампа LINQPad не делает то же самое? Редактировать: См. Связанный вопрос о том, как VS делает это: Как отладчик / интерактивное окно Visual Studio выводит свойства COM-объектов в.NET?

ArcObjects .NET SDK включает в себя PIA с RCW для каждого CoClass, которым может быть реализован COM-интерфейс, поэтому я думаю, что должна быть возможность обернуть эти объекты программным способом.

В качестве обходного пути я успешно использовал Marshal.CreateWrapperOfType() в моих запросах LINQ, чтобы заставить LINQPad выводить свойства объекта, когда я узнал, какой CoClass следует использовать. Конечно, это только правильно сбрасывает свойства типа значения - любые свойства ссылочного типа на основе COM все еще сообщаются как System.__ComObject так что правильное решение должно работать рекурсивно, чтобы обернуть их также.

В предыдущем вопросе я узнал, что CoClass может быть определен во время выполнения, если он реализует IPersist, что делает большая часть ArcObjects. Могу ли я каким-то образом использовать эту технику или другую для автоматического System.__ComObject в соответствующий RCW из PIAs? И если да, то как я могу реализовать это в LINQPad, например, предоставляя ICustomMemberProvider реализация? Можно ли сделать это рекурсивным, чтобы обернуть свойства, которые также являются COM-объектами?

Я использую LINQPad 4.x, нацеленный на.NET 4.0, но также заинтересован в поддержке LINQPad 2.x (поэтому предпочтение отдается решениям, которые работают как на.NET 3.5, так и.NET 4.0, но это не является обязательным требованием).

Обновление: я выяснил первую часть моего вопроса, которая заключалась в том, как обернуть System.__ComObject в своем RCW, используя CLSID, возвращенный IPersist.GetClassID, Посмотрите этот связанный вопрос и этот ответ для кода, который я использую.

Я все еще хотел бы знать, как я могу сделать это в метод дампа LINQPad.

1 ответ

У меня были некоторые из тех же проблем (за исключением того, что я работаю с библиотекой 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.

Другие вопросы по тегам