在C#中,重写(Override)是面向对象编程的核心概念,用于子类为继承自父类的虚方法(virtual)、抽象方法(abstract)或已重写的方法提供新的实现。在CAD(如AutoCAD)二次开发中,对图元进行重写通常意味着创建自定义实体,这需要深入理解CAD的API和对象模型。
C# 方法重写的基本用法
重写通过 override 关键字实现,其基本规则如下:
| 特性 | 基类方法 | 子类方法 | 说明 |
|---|---|---|---|
| 虚方法重写 | 使用 virtual 修饰 |
使用 override 修饰 |
最常见的重写形式,提供多态性。 |
| 抽象方法实现 | 使用 abstract 修饰 |
使用 override 修饰 |
子类必须提供实现。 |
| 密封重写 | 已使用 virtual 或 override |
使用 override 和 sealed修饰 |
阻止该方法的进一步重写。 |
| 隐藏(非重写) | 任何可访问方法 | 使用 new 修饰 |
创建新方法,不参与多态,不推荐轻易使用。 |
核心代码示例:
csharp
public class BaseEntity
{
// 1. 虚方法:提供默认实现,允许子类重写
public virtual void Draw()
{
Console.WriteLine("绘制基础图元");
}
// 2. 抽象方法:无实现,强制子类重写 public abstract double CalculateArea();
}
public class MyCircle : BaseEntity
{
// 使用 override 重写虚方法 public override void Draw()
{
base.Draw(); // 可选:调用基类实现 Console.WriteLine("绘制自定义圆形");
// 添加自定义绘制逻辑 }
// 必须重写抽象方法
public override double CalculateArea()
{
return Math.PI * Radius * Radius;
}
}
CAD二次开发中重写图元的注意事项
在AutoCAD等CAD平台进行二次开发时,创建自定义图元(即重写或扩展原生实体)是一项高级任务,需严格遵循其API规范。
1. 核心机制:从原生类派生
AutoCAD .NET API允许从特定原生类(如 Entity)派生以创建自定义对象。关键类是 CustomObject 及其子类,但更常见的做法是重写已有实体的行为或创建全新的 DBObject。
基本步骤示例:
csharp
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
// 自定义实体类必须继承自相应的CAD基类,例如Entity
public class MyCustomEntity : Entity
{
// 必须重写的核心方法
public override void SubWorldDraw(WorldDraw draw)
{
// 实现自定义的图形绘制逻辑
// 例如,使用draw.Geometry.Circle等绘制图元
base.SubWorldDraw(draw);
}
public override bool WorldDraw(WorldDraw wd)
{
// 处理世界空间中的绘制
return base.WorldDraw(wd);
}
public override void GetGripPoints(
GripDataCollection grips, double curViewUnitSize, int gripSize, Vector3d curViewDir,
GetGripPointsFlags bitFlags)
{
// 重写以定义自定义夹点
base.GetGripPoints(grips, curViewUnitSize, gripSize, curViewDir, bitFlags);
}
// 必须实现的事务处理克隆 public override DBObject Clone()
{
MyCustomEntity cloned = base.Clone() as MyCustomEntity;
if (cloned != null)
{
// 深拷贝自定义字段 }
return cloned;
}
}
2. 必须注意的关键事项
| 注意事项 | 说明与解决方案 |
|---|---|
| 正确的类继承 | 必须从CAD API中允许派生的类继承,如 Entity、Curve 或 CustomObject。直接重写密封类(如 DBPoint)通常不被允许。 |
| 重写核心图形方法 | WorldDraw、ViewportDraw 和 SubWorldDraw 是图形显示的核心,必须正确重写以确保图元在所有视图和布局中正确渲染。 |
| 处理对象持久化 | 自定义实体必须正确序列化和反序列化。需重写 DwgOut 和 DwgIn 方法,或使用 RXObject 类进行注册,并妥善管理自定义数据的读写。 |
| 注册自定义类 | 在CAD中使用自定义实体前,必须使用 RXClass 机制向数据库运行时注册该类,否则CAD无法识别和加载它。 |
| 夹点与编辑行为 | 重写 GetGripPoints 和 MoveGripPointsAt 以支持用户通过夹点交互式编辑你的图元。 |
| 边界框计算 | 重写 GetGeomExtents 方法,返回图元的精确边界框,这对于缩放、重生成和选择至关重要。 |
| 与命令流和事务集成 | 自定义实体的创建、修改和删除必须完全封装在CAD事务(Transaction)中,确保数据一致性和撤销/重做功能正常工作。 |
| 性能优化 | 在重写的绘制方法中,避免复杂计算。对于复杂几何图形,考虑使用代理图形或根据视图细节级别(LOD)简化图形。 |
| 资源管理 | 如果自定义实体使用了非托管资源(如句柄、内存),必须确保正确实现 Dispose 模式或在事务回滚时进行清理,防止内存泄漏。 |
| 兼容性与版本控制 | 为自定义实体的数据存储结构定义版本号,确保未来版本的程序能正确读取旧版本创建的图元。 |
3. 高级实践:使用自定义对象创建器
通常,更推荐使用 CustomObject 创建全新的对象类型,而非直接重写现有图元。这需要实现 ICustomObject 接口和相应的创建器。
csharp
// 简化的自定义对象创建示例
public class MyEntityCreator : ICustomObjectCreator
{
public void CreateCustomObject(ObjectId objectId)
{
using (Transaction tr = objectId.Database.TransactionManager.StartTransaction())
{
// 创建自定义实体实例
MyCustomEntity ent = new MyCustomEntity();
// ... 设置实体属性 ...
BlockTableRecord btr = tr.GetObject(
objectId, OpenMode.ForWrite) as BlockTableRecord;
btr.AppendEntity(ent);
tr.AddNewlyCreatedDBObject(ent, true);
tr.Commit();
}
}
}
总结 :在C#中进行CAD图元重写,本质是遵循CAD平台的特定对象模型进行继承和扩展。关键在于准确重写图形绘制、数据持久化和用户交互相关的方法 ,并严格在CAD的事务管理和内存管理框架内操作。务必参考对应CAD版本(如AutoCAD)的官方 .NET API 文档,因为具体可重写的类和方法会因版本而异。