本节摘要:组件式与服务端是重型装备,日常需求里的大头其实用轻武器就能解决。本节讲两条轻量路线:插件把一个功能挂进桌面端菜单,脚本把重复批处理交给机器。二八定律在这里最灵验——八成的零散需求,用两成的学习成本覆盖。
科室内业人员最常提的需求长这样:"能不能加个按钮,点一下就把当前图层的拓扑问题全查出来?"他们不想学新软件,就想在天天用的桌面端里多一个按钮。这正是插件的用武之地——宿主程序提供界面、数据管理、地图显示这些重资产,插件只写业务增量。
插件的运行机制一句话讲清:宿主启动时扫描插件目录,发现实现了约定接口的动态库,调用其初始化方法,插件趁机把自己的命令注册进菜单。画成流程:
流程图里最重要的角色是"宿主上下文"——初始化时宿主递给插件的那个对象。拿它才能取到当前地图、当前图层、当前选择集。插件代码里最常见的错误不是逻辑错,是绕过上下文自己另开数据连接,结果用户在界面里改了数据,插件读到的还是旧库。
一个最小可用的插件骨架如下,注册一个"统计当前图层要素数"的命令:
using System.Windows.Forms; public class CountPlugin : IMapGISPlugin { private IApplication app; // 宿主上下文 初始化时拿到 public string Name => "图层统计"; public string Caption => "统计当前图层要素数"; public void Initialize(IApplication host) { app = host; // 存住上下文 这是插件的命根 app.Commands.Register(this); // 向宿主注册命令 } public void Execute() { var layer = app.ActiveMap.GetLayer(0); // 取当前激活图层的第0层 if (layer == null) { MessageBox.Show("请先打开一个地图并激活图层"); return; } int n = layer.FeatureCount; // 经宿主上下文取数 保证是最新状态 MessageBox.Show("图层 " + layer.Name + " 共 " + n + " 个要素"); } public void Uninitialize() { /* 释放自建资源 上下文由宿主管 */ } } // 编译为动态库放入插件目录 重启宿主 菜单出现新命令 // 输出:点命令 弹窗 图层 耕地图斑 共 38421 个要素
插件的开发循环比组件式短得多:改代码、编译、拷贝动态库、重启宿主、点菜单验证。五个动作两分钟一轮。唯一的纪律是版本对齐——宿主升级后插件要回归测试,接口签名变了就得改代码重编,这是借壳的代价。
脚本路线的适用特征更明确:流程固定、无需界面、按批或按定时执行。判断口诀——"同一个操作做过第三次,就该写成脚本了"。
数据进厂环节的经典场景:测绘队每周交一批 CAD 宗地图,转要素类、统一属性字段名、算椭球面积、写质检标志,四步工序对几十个文件重复执行。手工做一晚,脚本做一分钟:
# 概念演示:宗地图批量进厂脚本(桌面端脚本接口 示意写法) import os import mapgis_dev as mg # 桌面端脚本开发模块 SRC = "宗地图收件目录" # 本周收件 OK = "进厂合格目录" steps_log = [] # 过程留痕 供质检回看 for name in os.listdir(SRC): if not name.endswith(".dwg"): continue # 只处理CAD文件 path = os.path.join(SRC, name) fc = mg.import_cad(path, target_gdb="耕地保护库") # 步骤1 转要素类 fc.rename_fields({"地块号": "宗地编号", "权利人": "权属单位"}) # 步骤2 字段统一 fc.add_area_field("椭球面积") # 步骤3 法定口径面积 bad = fc.check(拓扑="悬挂,缝隙", 面积="负值") # 步骤4 质检 if bad.count == 0: fc.move_to(OK) # 全过 进合格目录 steps_log.append((name, "通过", fc.count)) else: steps_log.append((name, "退回", str(bad.detail))) # 问题清单回传测绘队 for row in steps_log: print(row) # 输出示例: # (宗地007.dwg, 通过, 12) (宗地008.dwg, 退回, 悬挂点2处 缝隙1处) (宗地009.dwg, 通过, 8) # 定时执行:挂到操作系统的计划任务 每周五晚跑 周一上班看结果
脚本的两个工程习惯决定它是资产还是负债。留痕:每次运行把输入、输出、退回原因写成日志,出了争议有据可查,上面的 steps_log 就是为此。进版本库:脚本散落在各人机器桌面上的团队,脚本死了没人能救;进了版本库,人走了脚本还在跑。
阅读完本节,你应当能够:
插件与脚本常在一个科室里合流成"个人工具箱":白天内业用插件点按钮,夜里批处理靠脚本跑定时任务。它们共享同一套对象模型——6.2 啃下的四级结构在插件里是宿主上下文下的对象,在脚本里是模块直接给的对象。这就是本章把组件式放在最前面讲的原因:对象模型是三条路线公共的地基。
工具箱的积累是复利型的。第一年攒下十个插件五个脚本,第二年新同事入职直接继承整套工具,科室的产能就和别人不一样。第 7 章的行业案例里,那些"三天出一个成果"的标杆项目,背后几乎都有一个沉淀多年的工具箱。
⚠️ 常见坑:脚本没有失败处理,半夜跑到第三个文件崩了,剩下四十个文件没人管,周一来看"跑了一半"。批处理脚本必须有整体的事务观念——逐文件容错(单文件失败记录后继续)、末尾汇总报告(成功多少退回多少)、关键步骤可重跑(幂等设计,重跑不会重复入库)。