BlockTable索引器支持字符串和ObjectId键
在 AutoCAD .NET API 中,BlockTable类的索引器主要用于通过特定的键(Key)来获取对应的BlockTableRecord的ObjectId。其支持的键类型是明确的,主要包括以下两种:
1. 索引器的定义与支持的键类型
BlockTable类继承自DBDictionary,其索引器在底层实际上是通过DBDictionary的GetAt()方法实现的。根据官方 API 文档和通用实践,其索引器主要支持以下两种键类型:
| 键类型 | 描述 | 典型示例 |
|---|---|---|
string(字符串) | 最常用。通过块记录的名称(Block Name)来获取。块名不区分大小写。 | bt["MyBlock"]或bt["*Model_Space"] |
ObjectId | 通过块记录本身的ObjectId来获取其自身的ObjectId。这种用法在某些特定场景下有用,例如使用BlockTableRecord.ModelSpace这个静态属性返回的ObjectId。 | bt[BlockTableRecord.ModelSpace] |
2. 代码示例与详细说明
示例 1:使用字符串键
这是最直观和常见的用法,用于通过块名访问用户定义的块或特殊块(如模型空间、图纸空间)。
using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.ApplicationServices; using (Transaction trans = db.TransactionManager.StartTransaction()) { // 获取块表 BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; // 1. 访问用户自定义的块 string customBlockName = "MyDoorBlock"; if (bt.Has(customBlockName)) // 检查块是否存在 { ObjectId blockRecordId = bt[customBlockName]; // 使用字符串键 BlockTableRecord btr = trans.GetObject(blockRecordId, OpenMode.ForRead) as BlockTableRecord; // ... 操作块定义 } // 2. 访问特殊块:模型空间和图纸空间 // AutoCAD 内部使用特定的名称来标识这些特殊块。 ObjectId modelSpaceId = bt["*Model_Space"]; // 模型空间的内部名称 ObjectId paperSpaceId = bt["*Paper_Space"]; // 图纸空间的内部名称 // 然而,更推荐使用提供的常量来避免记忆内部名称 // ObjectId modelSpaceId = bt[BlockTableRecord.ModelSpace]; // 见下文 trans.Commit(); }示例 2:使用 ObjectId 键
这种用法看起来有些反直觉,因为它用块记录的ObjectId作为键去获取同一个ObjectId。它的主要用途是提供一种统一、类型安全的方式来访问块表,特别是在你已经拥有一个ObjectId并想确认它是否在块表中,或者进行统一处理时 。
using (Transaction trans = db.TransactionManager.StartTransaction()) { BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; // 假设我们已经通过其他方式获得了模型空间的 ObjectId ObjectId knownModelSpaceId = BlockTableRecord.ModelSpace; // 使用 ObjectId 作为键进行访问 ObjectId retrievedId = bt[knownModelSpaceId]; // retrievedId 将与 knownModelSpaceId 相同 // 这等同于一个“查找”操作,确认该 ID 存在于块表中。 // 在底层,它可能是通过 ID 对应的句柄或内部标识符进行查找的。 BlockTableRecord modelSpace = trans.GetObject(retrievedId, OpenMode.ForRead) as BlockTableRecord; // ... 后续操作 trans.Commit(); }关键点:bt[BlockTableRecord.ModelSpace]是这种用法的一个典型应用。BlockTableRecord.ModelSpace属性返回的就是模型空间块的ObjectId,将其作为索引器的键传入,返回的仍然是这个ObjectId。这提供了一种语法上的一致性。
3. 重要注意事项与内部机制
返回值始终是
ObjectId
无论使用字符串还是ObjectId作为键,索引器返回的值都是目标BlockTableRecord的ObjectId,而不是BlockTableRecord对象本身。必须通过Transaction.GetObject()打开才能获得可操作的对象。键不存在时的行为
如果使用一个不存在的字符串块名或无效的ObjectId作为键,索引器访问将抛出一个Autodesk.AutoCAD.Runtime.Exception异常(通常是eKeyNotFound)。因此,在不确定键是否存在时,应先使用BlockTable.Has()方法进行检查。string blockName = "NonExistentBlock"; if (bt.Has(blockName)) { ObjectId id = bt[blockName]; } else { Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; ed.WriteMessage($"
块 '{blockName}' 不存在。");
}
```
模型空间与图纸空间的访问
- 传统方式:可以直接使用它们的内部名称字符串
"*Model_Space"和"*Paper_Space"。 - 推荐方式:使用
BlockTableRecord类提供的静态属性,代码意图更清晰,且避免了记忆内部字符串。BlockTableRecord.ModelSpace– 获取模型空间ObjectId。BlockTableRecord.PaperSpace– 获取图纸空间ObjectId(当前布局)。
这些属性返回的ObjectId可以直接用作BlockTable索引器的键 。
- 传统方式:可以直接使用它们的内部名称字符串
索引器与
GetAt()方法BlockTable的索引器内部调用了其父类DBDictionary的GetAt()方法。GetAt()方法明确支持string和ObjectId两种重载形式,这从根源上解释了索引器支持这两种类型的原因。
总结:AutoCAD .NET API 中BlockTable索引器主要支持string(块名称)和ObjectId(块记录的对象ID)两种键类型。使用字符串键是访问用户定义块的标准方式;使用ObjectId键则提供了一种类型安全且统一的方式来访问已知的块记录(尤其是像BlockTableRecord.ModelSpace这样的系统常量)。无论使用哪种键,都应养成先检查存在性 (Has方法) 再访问,并通过事务获取目标对象的良好习惯 。
参考来源
- C#索引器使用详解
