兵器升级之IFoxCad库
使用CAD原生API进行二次开发代码过于繁琐,IFoxCad是一个更高层次的库,它对原生API进行了大量封装,可以让我们的代码更加简洁,显著提升我们的开发效率。一起升级我们的兵器吧!
环境搭建
-
安装项目模板
1 | # 安装项目模板,注意装最新版 |
- 创建IFoxCadTemplate项目,项目结构如下所示,可以修改AutoCAD.NET的版本
- 如何实现“主项目+子项目”的工程方案?
以上通过模板创建的项目引入了IFox.Basal.Source和IFox.CAD.Source两个源码包,这意味着该源码会被编译到生成文件中。
如果整个工程中只有一个这样的项目,那么完全没问题;但是,如果采用“主项目+子项目”的开发方案,势必相同代码会同时存在主库和子库中,从而导致编译出错。如何解决这个问题呢?
很简单,我们采用模板新建一个Base项目,它的作用只是引入IFox.Basal.Source和IFox.CAD.Source源码包。对于主项目和子项目,同样采用模板创建,但创建完成之后,需要删除两个IFox源码包。这种方法就避免了相同源码包含在多个生成文件中的问题。
核心用法
图元创建和添加
IFoxCad提供了一系列扩展方法,用于创建常见图元:
1 | // 两点画圆 |
可以由Point3d的List直接创建多段线:
1 | var pts = new List<Point3d> |
在IFoxCad中,事务处理和图元添加操作大大简化。
1 | [ ] |
“九表多词典”的增删改查
对“九表多词典”进行增删改查是日常开发面临最多的操作,IFoxCad库提供了非常方便的方法。DBTrans中有大量属性直接指向这些核心表和词典。可以直接从DBTrans拿到各种表和词典对象。
- 表查:可以统一使用Has方法
1 | using DBTrans tr = new(); |
- 表增:可以使用相同形式的Add方法,第一个参数通常是名称,第二个参数是Action,在该Action中可以指定新创建记录的各种属性
1 | using var tr = new DBTrans(); |
- 表改:可以使用相同形式的Change方法,第一个参数通常是名称,第二个参数是Action,在该Action中可以指定新属性值
1 | using var tr = new DBTrans(); |
- 表删:对不同表记录的删除方法有所差异
1 | tr.BlockTable.Remove("自定义块"); |
- 词典
通过DBTrans可以拿到各种常用的词典,其类型为DBDictionary,实现了IDictionary接口,是一个字典数据结构,对其进行增删改查很方便。
1 | DBDictionary dict = tr.MLStyleDict; |
以下给一个综合实例,涉及到对图层表、块表、文字样式表的操作:
1 | [ ] |
扩展数据
- 添加扩展数据
1 | var line1 = new Line(new Point3d(0, 0, 0), new Point3d(100, 600, 0)); |
- 删除扩展数据,针对某一注册程序下的扩展数据,可以删除所有或者指定的扩展数据
1 | using DBTrans tr = new(); |
- 获取扩展数据,也需要遍历判断,这一点封装不是很直接
1 | using DBTrans tr = new(); |
- 修改扩展数据,非常方便
1 | ent.ChangeXData("李浩数据2", DxfCode.ExtendedDataAsciiString, "nonofun"); |
过滤器
使用原生API编写复杂图元过滤器,经常是一件痛苦的事,IFoxCad进一步封装,使得代码更直观地呈现布尔含义。
1 | var fd = |
与以下Lisp过滤器含义相同:
关键语法解析
扩展方法
C#提供扩展方法机制,可以为既有类创建一些方法,使用起来就像是类自己的成员方法一样,调用起来更方便。
这种语法机制在框架设计中大量用到,特别基于既有库进行二次封装。
Action和Func的妙用
在IFoxCad库中大量使用到如下代码形式:
1 | tr.BlockTable.Add("自定义块1", |
该函数原型如下,最后三个参数都是Action或者Func类型:
1 | public static ObjectId Add(this SymbolTable<BlockTable, BlockTableRecord> table, |
为什么使用Action或者Func作为参数可以给相应的符号表添加符号表记录呢?原因其实很简单,看下列示例代码就一目了然:
1 | internal class Program { |
在函数内部,通过调用Action和Func,可以得到新的实例,将这些实例添加到目标数组中即可。
由于Lambda表达式可以为Action和Func形参传参,所以就可以极大简化代码,很巧妙!