惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
N
News and Events Feed by Topic
D
DataBreaches.Net
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Engineering at Meta
Engineering at Meta
T
Tailwind CSS Blog
博客园_首页
Microsoft Azure Blog
Microsoft Azure Blog
Y
Y Combinator Blog
博客园 - Franky
Hugging Face - Blog
Hugging Face - Blog
月光博客
月光博客
A
About on SuperTechFans
I
InfoQ
S
Securelist
Last Week in AI
Last Week in AI
S
Schneier on Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
Hacker News: Ask HN
Hacker News: Ask HN
Schneier on Security
Schneier on Security
Know Your Adversary
Know Your Adversary
腾讯CDC
大猫的无限游戏
大猫的无限游戏
S
Security @ Cisco Blogs
博客园 - 三生石上(FineUI控件)
Simon Willison's Weblog
Simon Willison's Weblog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tor Project blog
美团技术团队
aimingoo的专栏
aimingoo的专栏
G
Google Developers Blog
罗磊的独立博客
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
The Cloudflare Blog
S
Secure Thoughts
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Latest news
Latest news
Recent Announcements
Recent Announcements
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
L
LINUX DO - 热门话题
Security Latest
Security Latest
TaoSecurity Blog
TaoSecurity Blog
Cyberwarzone
Cyberwarzone
有赞技术团队
有赞技术团队

博客园 - 我才是银古

第16章:常见问题、排错与最佳实践 第15章:扩展生态、MCAD 与外部集成 第12章:实战案例:机械结构与 3D 打印零件 第14章:构建、测试、调试与贡献流程 第13章:OpenSCAD 源码架构与核心执行流程 第11章:预览、渲染、网格精度与性能优化 第09章:列表推导、递归与算法建模 第08章:参数化零件库与复用设计 第10章:导入导出、命令行与自动化 第06章:CSG 布尔建模方法 第07章:二维图形、拉伸、旋转与投影 第05章:基础几何、坐标系与变换 第04章:参数、变量、函数、模块与作用域 OpenSCAD 教程目录 第03章:OpenSCAD 语言基础 第02章:安装、环境配置与开发工作流 第01章:OpenSCAD 项目全景与学习路线 第02章:源码获取、编译与开发环境配置 第01章:OCCT项目全景与学习路线 第18章:二次开发实战与综合案例 第18章:综合实战案例 第17章:数据交换与协同 第16章:源码架构与二次开发 第15章:插件与自定义工作台开发 第14章:Python脚本宏与自动化 第13章:FEM仿真分析 第12章:CAM数控加工 第11章:SurfaceMesh与逆向工程 第10章:Draft二维绘图与BIM建筑 第09章:工程图TechDraw 第07章:参数化表达式与Spreadsheet 第08章:装配设计Assembly 第06章:Part工作台与几何内核 第05章:PartDesign实体特征建模 第04章:草图Sketcher约束建模 第02章:安装版本与工作环境配置 第03章:界面工作台与基础操作 第01章:项目全景与学习路线 第十二章:插件开发、研究功能与最佳实践 第十章:定时任务与自动化(Cron) 第七章:技能、记忆与自学习闭环 第八章:MCP 集成与上下文文件 第六章:工具系统与终端后端 第五章:模型供应商与配置体系 Hermes Agent 教程目录 第十一章:语音、视觉、浏览器与子代理协作 第四章:CLI/TUI 与会话管理 第十二章:学习路线、实战方案与最佳实践 第十一章:源码结构、开发调试与插件开发 第十章:自动化、远程访问、日志与排障 第九章:Control UI、节点、Canvas 与语音能力 第七章:工具、技能、插件与能力扩展 第八章:安全模型、访问控制与沙箱实践 第六章:Agent 工作区、会话与多智能体路由 第五章:多通道消息接入与聊天平台配置 第四章:配置体系、模型接入与认证管理 第三章:Gateway 架构、协议与运行机制 第二章:安装、环境准备与快速上手 第一章:OpenClaw 项目概览与核心定位 oh-my-openagent 教程目录 09-命令模型回退与配置参考 10-实战案例最佳实践与故障排除 05-工作模式-Ultrawork-Prometheus-Atlas 08-Hooks与MCP系统 06-Category与Skill系统 07-核心工具链 04-智能体全景详解 03-安装与环境配置 02-整体架构与多模型编排机制 01-项目简介与核心理念 01-项目概览与学习路线 02-安装部署与工具适配 03-Skill机制与using-superpowers 05-TDD系统化调试与完成前验证 04-需求澄清方案设计与计划编写 07-并行智能体子智能体与Git-Worktree 第六章:代码审查、反馈处理与分支收尾 08-中国特色Skills与本土团队落地 09-MCP构建工作流执行与自定义Skill 第23章:FreeCAD-Python-API Clipper2 C# 源码解读教程 第19章:PolyTree 多边形树结构 第20章:实际应用与最佳实践 第18章:Minkowski 和与差 第17章:RectClip 矩形裁剪优化 第16章:ClipperOffset 偏移类详解 第15章:填充规则详解 第14章:布尔运算执行流程 第13章:ClipperD 浮点裁剪类 第11章:OutRec 与 OutPt 输出结构 第9章:Active 活动边结构 第10章:Vertex 顶点与 LocalMinima 局部极小值 第12章:Clipper64 裁剪类详解 第7章:高精度运算与128位整数 第8章:ClipperBase 基类详解 第5章:枚举类型与常量定义 第6章:InternalClipper 内部工具类 第2章:核心数据结构 - Point64、PointD 第3章:路径与多边形表示 - Path64、PathD、Paths64、PathsD 第4章:矩形边界 - Rect64、RectD
插件系统与扩展开发
我才是银古 · 2026-06-20 · via 博客园 - 我才是银古

第十五章:插件系统与扩展开发

15.1 插件系统概述

15.1.1 Weikio Plugin Framework

LightCAD的插件系统基于Weikio Plugin Framework构建,这是一个.NET平台的轻量级插件加载框架,支持运行时动态加载和卸载程序集。

15.1.2 内置行业插件

LightCAD预置了五个行业插件:

插件 文件 大小 功能领域
QdArch QdArch.dll 591KB 建筑设计
QdElectric QdElectric.dll 45KB 电气设计
QdHvac QdHvac.dll 95KB 暖通设计
QdStruct QdStruct.dll 173KB 结构设计
QdWater QdWater.dll 201KB 给排水设计

15.2 插件加载机制

15.2.1 插件管理器

public class PluginManager
{
    private static List<IPlugin> loadedPlugins = new();
    private static string pluginDirectory;

    /// <summary>
    /// 加载指定目录下的所有插件
    /// </summary>
    public static void LoadPlugins(string directory)
    {
        pluginDirectory = directory;

        if (!Directory.Exists(directory))
        {
            Directory.CreateDirectory(directory);
            return;
        }

        var pluginFiles = Directory.GetFiles(directory, "*.dll");

        foreach (var pluginFile in pluginFiles)
        {
            try
            {
                LoadPlugin(pluginFile);
            }
            catch (Exception ex)
            {
                Console.WriteLine(
                    $"加载插件失败 {Path.GetFileName(pluginFile)}: {ex.Message}");
            }
        }
    }

    /// <summary>
    /// 加载单个插件
    /// </summary>
    private static void LoadPlugin(string pluginPath)
    {
        // 使用Weikio Plugin Framework加载
        var assembly = Assembly.LoadFrom(pluginPath);

        // 查找实现IPlugin接口的类型
        var pluginTypes = assembly.GetTypes()
            .Where(t => typeof(IPlugin).IsAssignableFrom(t)
                && !t.IsAbstract && !t.IsInterface);

        foreach (var pluginType in pluginTypes)
        {
            var plugin = (IPlugin)Activator.CreateInstance(pluginType);
            plugin.Initialize();
            loadedPlugins.Add(plugin);

            Console.WriteLine($"已加载插件:{plugin.Name} v{plugin.Version}");
        }
    }

    /// <summary>
    /// 获取所有已加载的插件
    /// </summary>
    public static IReadOnlyList<IPlugin> LoadedPlugins => loadedPlugins;

    /// <summary>
    /// 卸载所有插件
    /// </summary>
    public static void UnloadAll()
    {
        foreach (var plugin in loadedPlugins)
        {
            plugin.Shutdown();
        }
        loadedPlugins.Clear();
    }
}

15.2.2 插件接口

/// <summary>
/// 插件基础接口
/// </summary>
public interface IPlugin
{
    /// <summary>
    /// 插件名称
    /// </summary>
    string Name { get; }

    /// <summary>
    /// 插件版本
    /// </summary>
    string Version { get; }

    /// <summary>
    /// 插件描述
    /// </summary>
    string Description { get; }

    /// <summary>
    /// 插件作者
    /// </summary>
    string Author { get; }

    /// <summary>
    /// 初始化插件
    /// </summary>
    void Initialize();

    /// <summary>
    /// 关闭插件
    /// </summary>
    void Shutdown();
}

/// <summary>
/// 带命令注册能力的插件
/// </summary>
public interface ICommandPlugin : IPlugin
{
    /// <summary>
    /// 注册插件命令
    /// </summary>
    void RegisterCommands(CommandRegistry registry);
}

/// <summary>
/// 带UI扩展能力的插件
/// </summary>
public interface IUIPlugin : IPlugin
{
    /// <summary>
    /// 注册菜单项
    /// </summary>
    void RegisterMenuItems(MenuRegistry registry);

    /// <summary>
    /// 注册工具栏按钮
    /// </summary>
    void RegisterToolbarItems(ToolbarRegistry registry);

    /// <summary>
    /// 注册面板
    /// </summary>
    void RegisterPanels(PanelRegistry registry);
}

/// <summary>
/// 带元素类型扩展能力的插件
/// </summary>
public interface IElementPlugin : IPlugin
{
    /// <summary>
    /// 注册自定义元素类型
    /// </summary>
    void RegisterElementTypes(ElementTypeRegistry registry);
}

15.3 开发自定义插件

15.3.1 创建插件项目

# 创建类库项目
dotnet new classlib -n MyLightCADPlugin -f net10.0-windows

# 添加LightCAD核心引用
cd MyLightCADPlugin
dotnet add reference ../LightCAD.Core/LightCAD.Core.csproj
dotnet add reference ../LightCAD.Runtime/LightCAD.Runtime.csproj

15.3.2 实现插件

// MyPlugin.cs
public class MyPlugin : IPlugin, ICommandPlugin, IElementPlugin
{
    public string Name => "我的自定义插件";
    public string Version => "1.0.0";
    public string Description => "LightCAD自定义插件示例";
    public string Author => "开发者";

    public void Initialize()
    {
        Console.WriteLine("我的插件已初始化");
    }

    public void Shutdown()
    {
        Console.WriteLine("我的插件已关闭");
    }

    public void RegisterCommands(CommandRegistry registry)
    {
        registry.Register(new CommandInfo
        {
            Name = "MYCOMMAND",
            DisplayName = "我的命令",
            Description = "执行自定义操作",
            Action = ExecuteMyCommand
        });

        registry.Register(new CommandInfo
        {
            Name = "DRAWSTAR",
            DisplayName = "绘制星形",
            Description = "绘制一个正五角星",
            Action = DrawStar
        });
    }

    public void RegisterElementTypes(ElementTypeRegistry registry)
    {
        registry.Register(new ElementType
        {
            Guid = new LcGuid("my-plugin-star-element"),
            Name = "Star",
            DisplayName = "五角星",
            Category = "自定义图形",
            Is3D = false,
            Creator = () => new StarElement()
        });
    }

    private void ExecuteMyCommand()
    {
        // 自定义命令逻辑
        MessageBox.Show("执行自定义命令!");
    }

    private void DrawStar()
    {
        // 绘制五角星的逻辑
        var center = InputManager.GetPoint("指定五角星中心:");
        var radius = InputManager.GetDistance("指定外径:");

        var star = CreateStarPolyline(center, radius, 5);
        DocumentManager.Current.Entities.Add(star);
    }

    private LcPolyline CreateStarPolyline(Point2d center,
                                           double outerRadius, int points)
    {
        var polyline = new LcPolyline { IsClosed = true };
        var innerRadius = outerRadius * 0.382;

        for (int i = 0; i < points * 2; i++)
        {
            var angle = Math.PI / 2 + Math.PI * i / points;
            var r = (i % 2 == 0) ? outerRadius : innerRadius;
            polyline.AddVertex(new Point2d(
                center.X + r * Math.Cos(angle),
                center.Y + r * Math.Sin(angle)
            ));
        }

        return polyline;
    }
}

15.3.3 自定义元素类型

/// <summary>
/// 自定义五角星元素
/// </summary>
public class StarElement : LcEntity, IUpdateObject
{
    public Point2d Center { get; set; }
    public double OuterRadius { get; set; } = 50;
    public double InnerRadius { get; set; } = 19.1;
    public int Points { get; set; } = 5;
    public double Rotation { get; set; } = 0;

    public override string TypeName => "Star";

    public override BoundingBox2d Bounds
    {
        get
        {
            return new BoundingBox2d
            {
                Min = new Point2d(
                    Center.X - OuterRadius, Center.Y - OuterRadius),
                Max = new Point2d(
                    Center.X + OuterRadius, Center.Y + OuterRadius)
            };
        }
    }

    public override void TransformBy(Matrix4d matrix)
    {
        var p3d = new Point3d(Center.X, Center.Y, 0);
        var transformed = matrix.Transform(p3d);
        Center = new Point2d(transformed.X, transformed.Y);
    }

    public override LcEntity Clone()
    {
        return new StarElement
        {
            Center = Center,
            OuterRadius = OuterRadius,
            InnerRadius = InnerRadius,
            Points = Points,
            Rotation = Rotation,
            Color = Color,
            LayerName = LayerName
        };
    }

    public override double DistanceTo(Point2d point)
    {
        return point.DistanceTo(Center) - OuterRadius;
    }

    /// <summary>
    /// 获取五角星的顶点
    /// </summary>
    public List<Point2d> GetVertices()
    {
        var vertices = new List<Point2d>();
        for (int i = 0; i < Points * 2; i++)
        {
            var angle = Rotation + Math.PI / 2 + Math.PI * i / Points;
            var r = (i % 2 == 0) ? OuterRadius : InnerRadius;
            vertices.Add(new Point2d(
                Center.X + r * Math.Cos(angle),
                Center.Y + r * Math.Sin(angle)
            ));
        }
        return vertices;
    }

    public bool NeedsUpdate { get; private set; }
    public void OnUpdate(UpdateContext context)
    {
        NeedsUpdate = false;
    }
}

15.4 插件部署

15.4.1 编译和部署

# 编译插件
dotnet build -c Release

# 将编译输出复制到LightCAD的Plugins目录
copy bin/Release/net10.0-windows/MyLightCADPlugin.dll \
     ../LightCAD.WinForm/bin/Debug/net10.0-windows/Plugins/

15.4.2 插件清单文件

为了更好地管理插件信息,可以创建清单文件:

{
    "name": "MyLightCADPlugin",
    "version": "1.0.0",
    "author": "开发者",
    "description": "LightCAD自定义插件示例",
    "assembly": "MyLightCADPlugin.dll",
    "dependencies": [],
    "minimumLightCADVersion": "1.0.0"
}

15.5 ComponentActionLoader

15.5.1 操作加载器

ComponentActionLoader是LightCAD中专门用于加载建模操作的插件加载器:

public class ComponentActionLoader
{
    private Dictionary<string, IComponentAction> actions = new();

    /// <summary>
    /// 从程序集加载操作
    /// </summary>
    public void LoadActionsFromAssembly(Assembly assembly)
    {
        var actionTypes = assembly.GetTypes()
            .Where(t => typeof(IComponentAction).IsAssignableFrom(t)
                && !t.IsAbstract);

        foreach (var type in actionTypes)
        {
            var action = (IComponentAction)Activator.CreateInstance(type);
            actions[action.Name] = action;
        }
    }

    /// <summary>
    /// 获取操作
    /// </summary>
    public IComponentAction GetAction(string name)
    {
        return actions.TryGetValue(name, out var action) ? action : null;
    }

    /// <summary>
    /// 获取所有操作
    /// </summary>
    public IEnumerable<IComponentAction> GetAllActions()
    {
        return actions.Values;
    }

    /// <summary>
    /// 获取某个类别的操作
    /// </summary>
    public IEnumerable<IComponentAction> GetActionsByCategory(string category)
    {
        return actions.Values.Where(a => a.Category == category);
    }
}

public interface IComponentAction
{
    string Name { get; }
    string DisplayName { get; }
    string Category { get; }
    LcSolid3d Execute(ActionContext context);
}

15.6 扩展点总结

15.6.1 LightCAD可扩展的维度

扩展维度 接口/机制 说明
元素类型 IElementPlugin / ElementTypeRegistry 定义新的图元类型
命令 ICommandPlugin / CommandRegistry 添加新的用户命令
建模操作 IComponentAction / ComponentActionLoader 添加3D建模操作
UI菜单 IUIPlugin / MenuRegistry 扩展菜单系统
UI工具栏 IUIPlugin / ToolbarRegistry 添加工具栏按钮
UI面板 IUIPlugin / PanelRegistry 添加侧边面板
文件格式 IFormatPlugin / FormatConverter 支持新的文件格式
捕捉类型 ISnapProvider / SnapManager 自定义捕捉行为

15.7 本章小结

本章详细介绍了LightCAD的插件系统和扩展开发方法。LightCAD基于Weikio Plugin Framework提供了灵活的插件加载机制,支持运行时动态加载插件。通过IPlugin及其扩展接口(ICommandPlugin、IElementPlugin、IUIPlugin),开发者可以在多个维度上扩展LightCAD的功能。内置的五个行业插件展示了实际的插件应用场景。ComponentActionLoader专门用于加载3D建模操作,是建模扩展的核心入口。


上一章第十四章:文件格式与数据交换

下一章第十六章:命令与操作系统