Метод для извлечения свойств и атрибутов

Автор Тема: Метод для извлечения свойств и атрибутов  (Прочитано 7639 раз)

0 Пользователей и 5 Гостей просматривают эту тему.

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Здравствуйте!

Пишу метод для получения сведений о вставке блока - точке в чертеже, коллекции атрибутов, имени и слоя. Получился такой код
Код - C# [Выбрать]
  1. public static class BlockExtensions
  2.     {
  3.         [CommandMethod("9900")]
  4.         public static void MyMethod()
  5.         {
  6.             Document doc = Application.DocumentManager.MdiActiveDocument;
  7.             Database db = doc.Database;
  8.             Editor ed = doc.Editor;
  9.             var entities = SelectObjectsOnScreen();
  10.             Transaction tr = db.TransactionManager.StartTransaction();
  11.             using (tr)
  12.             {
  13.                 BlockReference bref = (BlockReference)tr.GetObject(entities[0].ObjectId, OpenMode.ForRead);
  14.                 var yyy = BlockRefPropertyExtractor(bref);
  15.                 tr.Commit();
  16.             }
  17.         }
  18.         public static List<Entity> SelectObjectsOnScreen()
  19.         {
  20.             Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  21.             Document doc = Application.DocumentManager.MdiActiveDocument;
  22.             Database db = doc.Database;
  23.             Transaction tr = db.TransactionManager.StartTransaction();
  24.  
  25.             List<Entity> listOfEntities = new List<Entity>();
  26.  
  27.             using (tr)
  28.             {
  29.                 // Request for objects to be selected in the drawing area
  30.                 PromptSelectionResult PrSeRes = doc.Editor.GetSelection();
  31.  
  32.                 // If the prompt status is OK, objects were selected
  33.                 if (PrSeRes.Status == PromptStatus.OK)
  34.                 {
  35.                     SelectionSet SelSet = PrSeRes.Value;
  36.  
  37.                     // Step through the objects in the selection set
  38.                     foreach (SelectedObject SelObj in SelSet)
  39.                     {
  40.                         // Check to make sure a valid SelectedObject object was returned
  41.                         if (SelObj != null)
  42.                         {
  43.                             // Open the selected object for write
  44.                             Entity entity = (Entity)tr.GetObject(SelObj.ObjectId, OpenMode.ForWrite);
  45.  
  46.                             if (entity != null)
  47.                             {
  48.                                 listOfEntities.Add(entity);
  49.                             }
  50.                         }
  51.                     }
  52.                 }
  53.  
  54.                 tr.Commit();
  55.             }
  56.  
  57.             return listOfEntities;
  58.         }
  59.         public static (ObjectId, Point3d, string, string, Dictionary<string, string>) BlockRefPropertyExtractor(BlockReference bref)
  60.         {
  61.             //--------------------------------------------------------------------Mandatory variables
  62.             Document doc = Application.DocumentManager.MdiActiveDocument;
  63.             Database db = doc.Database;
  64.             Editor ed = doc.Editor;
  65.             Transaction tr = db.TransactionManager.StartTransaction();
  66.             //--------------------------------------------------------------------Mandatory variables
  67.  
  68.             ObjectId objId = default;
  69.             Point3d basePoint = default;
  70.             string blockName = default;
  71.             string layer = default;
  72.             Dictionary<string, string> attributes = default;
  73.             BlockTableRecord block = null;
  74.             using (tr)
  75.             {
  76.                 objId = bref.BlockTableRecord;
  77.                 block = tr.GetObject(objId, OpenMode.ForRead) as BlockTableRecord;
  78.                 basePoint = bref.Position;
  79.                 blockName = bref.Name;
  80.                 layer = bref.Layer;
  81.                 if (bref.AttributeCollection.Count > 0)
  82.                 {
  83.  
  84.                     foreach (ObjectId att in bref.AttributeCollection)
  85.                     {
  86.                         AttributeDefinition attribute = tr.GetObject(att, OpenMode.ForRead) as AttributeDefinition;
  87.                         attributes.Add(attribute.Tag, attribute.TextString);
  88.                     }
  89.                 }
  90.                 tr.Commit();
  91.             }
  92.  
  93.  
  94.             return (objId, basePoint, blockName, layer, attributes);
  95.         }
  96.  
  97.     }
Хватаю fatal error при входе в BlockRefPropertyExtractor. В чем я неправ? Как исправить?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Какой-то у тебя уж очень странный синтаксис описания BlockRefPropertyExtractor
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Какой-то у тебя уж очень странный синтаксис описания BlockRefPropertyExtractor
Чтобы не делать класс-контейнер я возвращаю кортеж - можно с C# 7. Но ошибка по отладчику происходит на входе в метод, а не при выдаче результата.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
В SelectObjectsOnScreen ты возвращаешь массив примитивов, которые открыты (причем на запись), но они уже за пределами закрытой транзакции и соответственно недействительны. Мне так кажется, что на эти грабли ты уже наступал...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Еще одни грабли - не проверять результаты выполнения методов. А если выбраны не блоки? А если ничего не выбрано?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
но они уже за пределами закрытой транзакции и соответственно недействительны
Вот тут не понял - objectId же действительны в течение всей сессии, да и объекты никуда не исчезают - почему же тогда они недействительны?

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
которые открыты (причем на запись
Тут согласенб просто на этапе разработки я использую общий универсальный метод с максимальным функционалом, потом релизе все меняю на чтение.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
но они уже за пределами закрытой транзакции и соответственно недействительны
Вот тут не понял - objectId же действительны в течение всей сессии, да и объекты никуда не исчезают - почему же тогда они недействительны?
Объекты/примитивы открытые в транзакции действительны только в пределах самой транзакции.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
Переписал с меньшим числом транзакций - по-прежнему ошибка:
Код - C# [Выбрать]
  1.  public static class BlockExtensions
  2.     {
  3.         [CommandMethod("9900")]
  4.         public static void MyMethod()
  5.         {
  6.             Document doc = Application.DocumentManager.MdiActiveDocument;
  7.             Database db = doc.Database;
  8.             Editor ed = doc.Editor;
  9.             Transaction tr = db.TransactionManager.StartTransaction();
  10.             using ( tr )
  11.             {
  12.                 ObjectId id = default;
  13.                 PromptSelectionResult PrSeRes = doc.Editor.GetSelection();
  14.  
  15.                 // If the prompt status is OK, objects were selected
  16.                 if (PrSeRes.Status == PromptStatus.OK)
  17.                 {
  18.                     SelectionSet SelSet = PrSeRes.Value;
  19.  
  20.                     // Step through the objects in the selection set
  21.                     foreach (SelectedObject SelObj in SelSet)
  22.                     {
  23.                         // Check to make sure a valid SelectedObject object was returned
  24.                         if (SelObj != null)
  25.                         {
  26.                             id = SelObj.ObjectId;
  27.  
  28.                         }
  29.                     }
  30.                 }
  31.                 var yyy = BlockRefPropertyExtractor(id,tr);
  32.                 tr.Commit();
  33.             }
  34.         }
  35.        
  36.         public static (ObjectId, Point3d, string, string, Dictionary < string, string >) BlockRefPropertyExtractor(ObjectId id, Transaction tr)
  37.         {
  38.             ObjectId objId = default;
  39.             Point3d basePoint = default;
  40.             string blockName = default;
  41.             string layer = default;
  42.             Dictionary < string, string > attributes = default;
  43.             BlockReference bref = (BlockReference) tr.GetObject(id, OpenMode.ForRead);
  44.             BlockTableRecord block = (BlockTableRecord) tr.GetObject(bref.BlockTableRecord, OpenMode.ForRead);
  45.             blockName = block.Name;
  46.             block.Dispose();
  47.             basePoint = bref.Position;
  48.             layer = bref.Layer;
  49.             if ( bref.AttributeCollection.Count > 0 )
  50.             {
  51.                 AttributeCollection collection = bref.AttributeCollection;
  52.                 foreach ( ObjectId att in collection )
  53.                 {
  54.                     AttributeDefinition attribute = tr.GetObject(att, OpenMode.ForRead) as AttributeDefinition;
  55.                     attributes.Add(attribute.Tag, attribute.TextString);
  56.                 }
  57.             }
  58.  
  59.             return (objId, basePoint, blockName, layer, attributes);
  60.         }
  61.     }
Что можно еще попробовать?
« Последнее редактирование: 03-02-2020, 22:46:05 от Atomohod »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
1. Перепиши функцию без кортежа.
2. Транзакцию запускай когда она нужна.
3. Проверяй id на то, что он не null и соответствует BlockReference
4. Это зачем: block.Dispose(); ???
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн AtomohodАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 453
  • Карма: 1
4. Это зачем: block.Dispose(); ???
Нашел такое в блоге Киана Волмсли, зачем - я тоже не понимаю, вроде я table record не блокирую, зачем ее диспозить? Если у Вас есть какие-нибудь мысли на этот счет? Мне интересно  зачем он это добавил.



Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Мне интересно  зачем он это добавил.
В данном коде это совершенно лишнее и потенциально опасное, так как tr.Commit() вызовёт внутри себя повторно btr.Dispose().
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Переписал с меньшим числом транзакций - по-прежнему ошибка:
<...>
Что можно еще попробовать?
В BlockReference содержатся AttributeReference а не AttributeDefinition. См. строку 54.
Пример - в справке: http://help.autodesk.com/view/ACD/2015/ENU/?guid=GUID-BA69D85A-2AED-43C2-B5B7-73022B5F28F8