AutoCAD - получить все объекты, которые имеют свойство "Длина" - C# / динамический / отражение
(Даже если вы не знаете об Autocad, вы можете помочь, если знаете о динамических объектах C#)
Я пытаюсь создать команду Autocad, используя.NET (C#), которая позволяет пользователю выбирать объекты, а из этих объектов суммировать их длины.
Часть выбора в порядке, я смог получить список выбранных элементов либо как
- AcadEntity; или же
- DBObject
Но есть много подтипов AcadEntity, которые имеют свойство length. (Пример: AcadLine, AcadLWPolyline и т. Д.) - я не хочу знать во время компиляции, что это за типы, и я не могу доверять обычным пользователям Autocad использовать только один или два из этих типов.
Итак, я должен проверить, содержат ли эти объекты свойство "Длина" и получить это значение.
Очевидно, я могу сделать попытку поймать:
dynamic dynaEntity = (dynamic)AcadEntityInstance
try
{
double len = dynaEntity.Length;
LengthsPerType.AddOrSum(entityType, len);//personal method, no problem here
//entityType is a string found in AcadEntityInstance.ObjectName
//it returns an "AcDbLine", for instance, which is not an actual System.Type.
//The related Type is "AcadLine" - I can, for instance do (AcadLine)AcadEntityInstance
}
catch (System.Exception E) { }
Но, как вы знаете, создание множества исключений на самом деле не лучший способ программирования вещей. Итак, мне нужно чистое решение для этого.
Что я пробовал?
Получение свойств через отражение:
PropertyInfo prop = dynaEntity.GetType().GetProperty("Length"); PropertyInfo prop = AcadEntityInstance.GetType().GetProperty("Length"); PropertyInfo prop = ((object)AcadEntityInstance).GetType().GetProperty("Length");
Все они всегда возвращают "ноль"
Глядя на данные объекты, они "System.__ComObject". Свойство "Длина", если оно доступно, отображается в отладчике в "Развернуть динамическое представление".
- Получение значения свойства через строку с этим ответом здесь, где кто-то может использовать RuntimeBinder для получения свойства через строку... поэтому я предполагаю, что может быть способ проверить, существует ли оно перед вызовом, верно?
Этот код работает, но только если есть "Длина". Есть ли способ проверить это перед вызовом последней строки?
var ArgInfo = Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(0, null);
var getMember = Microsoft.CSharp.RuntimeBinder.Binder.GetMember(0, "Length", dynaEntity.GetType(), new[] { ArgInfo });
var site = System.Runtime.CompilerServices.CallSite<Func<System.Runtime.CompilerServices.CallSite, object, object>>.Create(getMember);
var result = site.Target(site, dynaEntity);
Как мне кажется, могут быть хорошие решения?
- Перечисление свойств динамического объекта - я нашел много вопросов по этому поводу, все они используют сторонние библиотеки, совсем ничего простого (если отладчик может их перечислять, почему я не могу?)
- Экземпляр или приведение к объекту AcDbCurve (если он существует в некоторой библиотеке, я могу отсутствовать). Я читал, что это родительский тип для всех кривых (которые я предполагаю, что содержат "Длина"). Но не существует IAcadCurve или чего-то подобного.
- Преобразование динамических объектов в ExpandoObjects или что-то вроде поиска интерфейса, содержащего перечисленные элементы.
Пока что нашел:
- Сторонние библиотеки - это действительно необходимо? Это действительно так сложно? - Я не могу использовать / установить их
- Один из упомянутых ранее ответов, который очень близок к нему, но один шаг отсутствует