На форуме adn-cis.org недавно появилось сообщение о том, что BlockTableRecord.HasAttributeDefinitions возвращает неверное значение для тех записей, из которых определения атрибутов на самом деле были ранее удалены. Наличие данного бага было подтверждено и заявка отправлена в ADN. Соответственно, придётся писать свою, корректную реализацию данного функционала.
По обозначенной выше ссылке проблема обозначалась следующим образом (отредактированная цитата):
По обозначенной выше ссылке проблема обозначалась следующим образом (отредактированная цитата):
1. Создаем определение блока c одним произвольным объектом (например с полилинией).
2. Добавляем определение атрибута в наше определение блока.
3. Видим, что свойство BlockTableRecord.HasAttributeDefinitions равно true, как и полагается.
4. Итерацией проходим по объектам нашей BlockTableRecord и видим, что их два: полилиния и определение атрибута.
5. Теперь удаляем ранее добавленное определение атрибута.
6.Итерацией проходим по объектам нашей BlockTableRecord и видим лишь один объект (как и полагается): полилинию.
7. Теперь смотрим свойство BlockTableRecord.HasAttributeDefinitions и видим, что оно равно true вместо ожидаемого false.
Свою версию обозначенного выше функционала реализуем в виде метода расширения, которому присвоим имя HasAttDefs:
Последовательно выполняем все шаги, демонстрирующие появление проблемы и запускаем команду TestBlock:
1: // BlockTableRecordExtentions.cs
2: // © Andrey Bushman, 2014
3: // Extention methods for the BlockTableRecord class
4: using System;
5: using System.Collections.Generic;
6: using System.Linq;
7: using System.Text;
8:
9: /// В целях переносимости кода и отсутствия в псевдонимах наименований
10: /// конкретного САПР, целесообразней формировать псевдонимы в
11: /// нейтральной форме, например: cad, вместо acad, Ap вместо AcAp, Db
12: /// вместо AcDb и т.д. Построенная таким способом система наименований
13: /// будет более удобной программисту, портирующему ваш код под другую
14: /// САПР. Ниже приведён вариант определений таких нейтральных псевдонимов
15: /// под некоторый набор различных САПР.
16: #if AUTOCAD
17: using cad = Autodesk.AutoCAD.ApplicationServices.Application;
18: using Ap = Autodesk.AutoCAD.ApplicationServices;
19: using Db = Autodesk.AutoCAD.DatabaseServices;
20: using Ed = Autodesk.AutoCAD.EditorInput;
21: using Gm = Autodesk.AutoCAD.Geometry;
22: using Rt = Autodesk.AutoCAD.Runtime;
23: #elif BRICSCAD
24: using cad = Bricscad.ApplicationServices.Application;
25: using Ap = Bricscad.ApplicationServices;
26: using Db = Teigha.DatabaseServices;
27: using Ed = Bricscad.EditorInput;
28: using Gm = Teigha.Geometry;
29: using Rt = Bricscad.Runtime;
30: #elif NANOCAD
31: using cad = HostMgd.ApplicationServices.Application;
32: using Ap = HostMgd.ApplicationServices;
33: using Db = Teigha.DatabaseServices;
34: using Ed = HostMgd.EditorInput;
35: using Gm = Teigha.Geometry;
36: using Rt = Teigha.Runtime;
37: #endif
38:
39: namespace Bushman.CAD.Extentions {
40: /// <summary>
41: /// Методы расширения для экземпляров класса BlockTableRecord
42: /// </summary>
43: public static class BlockTableRecordExtentions {
44: /// <summary>
45: /// Данный метод проверяет наличие экземпляров <c>Db.AttributeDefinition</c> в
46: /// составе объекта <c>BlockTableRecord</c> и представляет собой замену методу
47: /// <c>BlockTableRecord.HasAttributeDefinitions</c>, который реализован
48: /// неверно - в виду этого и возникла необходимость написать корректный вариант
49: /// реализации. Информация о некорректной работе
50: /// <c>BlockTableRecord.HasAttributeDefinitions</c> была подтверждена и
51: /// отправлена в ADN. Подробности на странице
52: /// http://adn-cis.org/forum/index.php?topic=625.0
53: /// </summary>
54: /// <param name="btr">экземпляр <c>BlockTableRecord</c>, подлежащий проверке.</param>
55: /// <returns>true - в составе указанного объекта <c>BlockTableRecord</c>
56: /// содержатся элементы <c>Db.AttributeDefinition</c>, иначе - false.</returns>
57: public static Boolean HasAttDefs(this Db.BlockTableRecord btr) {
58: String name = Rt.RXClass.GetClass(typeof(Db.AttributeDefinition)).Name;
59: return btr.Cast<Db.ObjectId>().Any(n => !n.IsNull && n.IsValid
60: && !n.IsErased && !n.IsEffectivelyErased && String.Equals(
61: n.ObjectClass.Name, name, StringComparison.InvariantCulture));
62: }
63:
64: #if DEBUG
65: /// <summary>
66: /// Команда, демонструрующая некорректную работу
67: /// <c>BlockTableRecord.HasAttributeDefinitions</c>
68: /// и корректность работы метода <c>HasAttDefs</c>.
69: /// За основу взят код
70: /// http://adn-cis.org/forum/index.php?topic=625.msg2168#msg2168
71: /// </summary>
72: [Rt.CommandMethod("TestBlock")]
73: public static void TestBlock() {
74: Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
75: Ed.Editor ed = doc.Editor;
76: Ed.PromptResult res = ed.GetString("\nType name of block: ");
77: if (res.Status != Ed.PromptStatus.OK) return;
78: using (Db.Transaction tr = doc.TransactionManager.StartTransaction()) {
79: Db.BlockTable bt = tr.GetObject(doc.Database.BlockTableId,
80: Db.OpenMode.ForRead) as Db.BlockTable;
81: if (bt != null) {
82: if (bt.Has(res.StringResult)) {
83: Db.BlockTableRecord btr = tr.GetObject(bt[res.StringResult],
84: Db.OpenMode.ForRead) as Db.BlockTableRecord;
85: if (btr != null) {
86: ed.WriteMessage("\nAutodesk: Block {0} has{1} attribute definitions.\n",
87: res.StringResult, btr.HasAttributeDefinitions ? "" : " not");
88: // Мною добавлена эта строка кода:
89: ed.WriteMessage("\nBushman: Block {0} has{1} attribute definitions.\n",
90: res.StringResult, btr.HasAttDefs() ? "" : " not");
91: }
92: }
93: else {
94: ed.WriteMessage("\nBlock {0} not found", res.StringResult);
95: }
96: }
97: tr.Commit();
98: }
99: }
100: #endif
101: }
102: }
Последовательно выполняем все шаги, демонстрирующие появление проблемы и запускаем команду TestBlock:
Комментариев нет:
Отправить комментарий