Здравствуйте, уважаемые старожилы и гости форума. Пишу макрос для TFlex CAD 10.0.57.0, который показывает информацию о выделенном объекте документа. В частности, для линий типа Outline пишу код:
Код
ModelObject mo = doc.Selection.GetAt(0) as ModelObject; //Исследуем первый выделенный объект
...
switch (mo.GroupType) //Перебираем тип объекта
...
case ObjectType.Outline: //Найдена линия изображения
Outline ol = mo as Outline;
if (ol == null)
{
MessageBox.Show("Объект определён как \"" + mo.GroupType.ToString() + "\", но при преобразовании к типу \"" +
"\"Outline\" объект получил значение null.");
try
{
ol = (ProjectionOutline)mo;
}
catch (Exception e)
{
ReportForm errForm = new ReportForm();
errForm.SetReportText(e.Message);
errForm.ShowDialog();
}
В документе я выбираю линию изображения, полученную с проекции (класс ProjectionOutline). Согласно документации на TFlex API имеем:
Код
__gc class ProjectionOutline : public Model2D::Outline;
Значит, я могу обращаться к ProjectionOutline через переменную базового класса Outline. При выполнении строки
Код
ol = (ProjectionOutline)mo;
генерируется исключение вот с таким сообщением (содержится в e.Message): [A]TFlex.Model.Model3D.ProjectionOutline невозможно привести к [B]TFlex.Model.Model3D.ProjectionOutline. Тип A происходит от ТFlехАРI3D, Version=9.0.0.0, Culture=neutral, PublicKeyToken=28c4a25ab632a509 в контексте "LoadFrom" в расположении "C:\PROGRA~1\T-FLEX\T-FLEX~3\Program\ТFlехАРI3D.dll. Тип B происходит от ТFlехАРI3D, Version=9.0.0.0, Culture=neutral, PublicKeyToken=28c4a25ab632a509" в контексте "Default" в расположении "C:\Program Files\T-FLEX\T-FLEX CAD 10\Program\ТFlехАРI3D.dll. Подскажите пожалуйста, что может быть не так? При компиляции проекта в свойствах ссылок на ТFlехАРI.dll и ТFlехАРI3D.dll свойство "CopyLocal == false". Буду благодарен за любые мысли по поводу причин происхождения вышеописанного сообщения. Просто не могу понять, куда дальше копать.
Николай пишет: Просто не могу понять, куда дальше копать.
При обращении к ProjectionOutline через переменную базового класса правильная работа не гарантирована. Специалисты говорят, что в этом случае надо использовать Dynamic Cast.
Вообще, было бы интересно узнать зачем вообще вам потребовалось ))
Здравствуйте, уважаемый Osiris2000. Спасибо за внимание к моей проблеме.
Цитата
При обращении к ProjectionOutline через переменную базового класса правильная работа не гарантирована.
Если возможно, поясните, почему нельзя обращаться к экземпляру класса TFlex.Model.Model3D.ProjectionOutline через переменную базового класса TFlex.Model.Model2D.Outline? И как мне можно было бы действовать наиболее корректно для решения следующей задачи: Мой макрос должен выводить информацию из свойств выбранного объекта. Для этого я получаю сперва 1й выбранный объект, остальные не рассматриваю:
Код
ModelObject mo = doc.Selection.GetAt(0) as ModelObject; //Исследуем первый выделенный объект
Затем проверяю, что же хранится в mo:
Код
switch (mo.GroupType) //Перебираем тип объекта
...
case ObjectType.Outline: //Найдена линия изображения
Outline ol = mo as Outline;
В данном случае я хочу только лишь считать свойства объекта типа Outline. Но если я выбираю линию на проекции и запускаю макрос, то mo будет содержать ссылку на экземпляр класса ProjectionOutline. Что может плохого произойти, когда выполнится строка:
Код
Outline ol = mo as Outline;
Понятно, что при любых накладках ol будет null. Но мне нужен "действительный" результат, для считывания данных или любых других операций.
Прошу прощения за оформление ответа в виде нескольких сообщений, но из-за длинных постов система меня банит.
Цитата
Вообще, было бы интересно узнать зачем вообще вам потребовалось ))
Код
ol = (ProjectionOutline)mo;
и всю обвязку с исключениями я написал для того, чтобы понять, почему при выборе линии с проекции я не могу считать с неё информацию. Потому что строка
Код
Outline ol = mo as Outline;
постоянно давала null. То есть только ради того, чтобы явным преобразованием выявить возникающее исключение и максимально подробно выяснить, что происходит. Хотя на самом деле то конечно дело не в макросе для получения информации, это я просто для примера привожу. У меня написано несколько макросов, работающих с линиями, работа идёт через переменные класса Outline. И всё работает, пока не начинаю выбирать для обработки линии с проекций. Поэтому очень хочу досконально разобраться, почему именно линии с проекций (класс ProjectionOutline) так странно себя ведёт при доступе через переменную Outline. Чувствую, что собака зарыта тут:
Код
class ProjectionOutline : public Model2D::Outline; //из документации на API
Ведь ProjectionOutline определён в сборке ТFlехАРI3D.dll, a Outline - в TFlexAPI.dll. И какой-то ньюанс на этом стыке видимо и возникает. Но какой?
Pln всегда получает значение null при выборе линии на проекции. Если я пишу вот так:
Код
Pln = (ProjectionOutline)mo;
то возникает то же самое исключение System.InvalidCastException с тем же самым сообщением про невозможность привести тип А к типу В. Есть странность: сборки ТFleхАРI.dll и ТFleхАРI3D.dll загружены 2 раза (перебираю AppDomain.CurrentDomain.GetAssemblies() ): Загруженные сборки:
Частично решил свою проблему, установив ТFleхАРI.dll и ТFleхАРI3D.dll в глобальный кеш сборок. Исключение System.InvalidCastException не выбрасывается, ТFleхАРI.dll и ТFleхАРI3D.dll перестали загружаться 2 раза. Макрос заработал, но я заметил странности: 1. при выборе линии на проекции её тип стал определяться как TFlex.Model.Model2D.Outline; 2. свойство Outline.SybType == Undefined. То есть если мне понадобится доступ к свойствам класса ProjectionOutline - ничего не выйдет. В чём глобальная причина выяснить так и не удалось, подозреваю, что на моей машине какие-то проблемы с NET Framework. При запуске макроса на другой машине с Windows 7 макрос отрабатывает абсолютно корректно, без установки ТFleхАРI.dll и ТFleхАРI3D.dll в GAC.