在C# CAD二次开发中,多段线(Polyline)的扩展数据(XData)主要用于为实体附加自定义的、非图形化的信息,以实现数据关联、流程控制或信息追溯等高级功能。
其核心用途可归纳为下表:
| 用途类别 | 具体说明 | 典型应用场景 |
|---|---|---|
| 存储自定义属性 | 将业务相关的属性(如构件ID、材料、状态、成本等)直接绑定到图形实体上。 | 在BIM或工程管理系统中,为多段线代表的管线、边界等存储其工程属性。 |
| 实现对象关联 | 通过存储其他实体的句柄(Handle)或唯一标识,建立图形对象之间的逻辑关系。 | 一条多段线(如道路中心线)通过扩展数据关联到多个标注或地块实体。 |
| 记录过程信息 | 保存实体创建、修改过程中的元数据,如创建者、时间、版本号或审批状态。 | 在协同设计流程中,追踪多段线的设计变更历史。 |
| 控制程序行为 | 存储特定标记或参数,供二次开发程序在运行时读取,以决定对实体的处理方式。 | 标记一条多段线是否需要被后续的批量处理程序忽略或进行特殊计算。 |
###核心操作代码示例
扩展数据的操作围绕 SetXData 和 GetXData 方法,并使用 ResultBuffer 来组织数据。数据以"类型-值"对(TypedValue)的形式存储。
- 为多段线写入扩展数据
以下代码演示如何为一条选中的多段线附加一个字符串类型的构件编号和一个整型的状态码。
csharp
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
public class XDataDemo
{
[CommandMethod("WritePolylineXData")]
public void WritePolylineXData()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// 1. 选择一条多段线
PromptEntityOptions opt = new PromptEntityOptions("
请选择一条多段线:");
opt.SetRejectMessage("
请选择多段线!");
opt.AddAllowedClass(typeof(Polyline), false);
PromptEntityResult res = ed.GetEntity(opt);
if (res.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// 2. 以写模式打开多段线对象 Polyline pl = tr.GetObject(res.ObjectId, OpenMode.ForWrite) as Polyline;
if (pl == null) return;
// 3. 创建扩展数据缓冲区 (ResultBuffer)
// 约定:注册应用名称为"MY_APP"
string regAppName = "MY_APP";
// 确保应用程序名称已注册到数据库
RegAppTable rat = tr.GetObject(db.RegAppTableId, OpenMode.ForRead) as RegAppTable;
if (!rat.Has(regAppName))
{
rat.UpgradeOpen();
RegAppTableRecord ratr = new RegAppTableRecord();
ratr.Name = regAppName;
rat.Add(ratr);
tr.AddNewlyCreatedDBObject(ratr, true);
}
// 4. 构建扩展数据内容 // 第一个TypedValue必须是注册应用程序名称 (1001, "MY_APP")
// 后续可跟多个自定义数据对 ResultBuffer rb = new ResultBuffer();
rb.Add(new TypedValue((int)DxfCode.ExtendedDataRegAppName, regAppName)); // 应用名 rb.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "BEAM-2024-001")); // 构件编号 (1000)
rb.Add(new TypedValue((int)DxfCode.ExtendedDataInteger16, 1)); // 状态码 (1070)
// 5. 将扩展数据赋给多段线 pl.XData = rb;
rb.Dispose(); // 释放ResultBuffer资源
tr.Commit();
ed.WriteMessage("
成功为多段线写入扩展数据。");
}
}
}
- 从多段线读取扩展数据
以下代码演示如何读取并解析已附加的扩展数据。
csharp
[CommandMethod("ReadPolylineXData")]
public void ReadPolylineXData()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityOptions opt = new PromptEntityOptions("
请选择一条带扩展数据的多段线:");
opt.SetRejectMessage("
请选择多段线!");
opt.AddAllowedClass(typeof(Polyline), false);
PromptEntityResult res = ed.GetEntity(opt);
if (res.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Polyline pl = tr.GetObject(res.ObjectId, OpenMode.ForRead) as Polyline;
if (pl == null) return;
// 获取扩展数据
ResultBuffer rb = pl.GetXDataForApplication("MY_APP");
if (rb == null)
{
ed.WriteMessage("
该多段线未找到'MY_APP'相关的扩展数据。");
return;
}
// 遍历并解析ResultBuffer中的TypedValue
ed.WriteMessage("
--- 扩展数据内容 ---");
foreach (TypedValue tv in rb)
{
// 根据DxfCode判断数据类型并输出
switch (tv.TypeCode)
{
case (int)DxfCode.ExtendedDataRegAppName:
ed.WriteMessage($"
应用名称: {tv.Value}");
break;
case (int)DxfCode.ExtendedDataAsciiString: // 1000
ed.WriteMessage($"
字符串数据: {tv.Value}");
break;
case (int)DxfCode.ExtendedDataInteger16: // 1070
ed.WriteMessage($"
短整型数据: {tv.Value}");
break;
// 可继续添加其他类型的处理,如1071(长整型)、1040(双精度浮点)等 default:
ed.WriteMessage($"
未知类型码[{tv.TypeCode}]: {tv.Value}");
break;
}
}
rb.Dispose();
tr.Commit();
}
}
关键注意事项1. 注册应用程序名称 :在写入扩展数据前,必须确保其关联的应用程序名称(如 "MY_APP")已存在于当前图形的注册应用程序表(RegAppTable)中,否则数据可能无法正确关联或读取。
- 数据类型与DxfCode :扩展数据支持多种数据类型,每种类型对应一个特定的
DxfCode(如1000代表字符串,1070代表16位整数)。必须使用正确的代码,否则在读取时会产生错误或乱码。 - 性能与存储:扩展数据存储在DWG文件内部,大量或过大的扩展数据会增加文件体积。对于海量复杂属性,应考虑使用外部数据库关联实体句柄(Handle)的方案。
- 事务管理:所有涉及数据库对象(包括扩展数据操作)的代码都必须置于事务(Transaction)中,以确保数据的一致性和完整性。