# 03-插件项目结构详解 了解插件项目的每个文件和文件夹的作用,是开发高质量插件的基础。本文将详细解析插件项目的完整结构。 --- ## 📂 项目结构概览 使用模板创建的插件项目结构如下: ``` MyPlugin/ ├── plugin.json # 插件清单(必需) ├── MyPlugin.csproj # 项目文件(必需) ├── Plugin.cs # 入口类(必需) ├── README.md # 项目说明(推荐) ├── .gitignore # Git忽略文件(可选) └── Localization/ # 本地化文件夹(可选) ├── zh-CN.json # 中文资源 └── en-US.json # 英文资源 ``` --- ## 📋 plugin.json - 插件清单 这是插件最重要的配置文件,定义了插件的元数据。 ### 完整示例 ```json { "id": "com.example.myplugin", "name": "我的插件", "description": "这是一个示例插件", "author": "作者名称", "version": "1.0.0", "apiVersion": "5.0.0", "entranceAssembly": "MyPlugin.dll", "sharedContracts": [], "website": "https://example.com", "icon": "icon.png", "tags": ["工具", "实用"] } ``` ### 字段详解 | 字段 | 必需 | 说明 | 示例 | |-----|------|------|------| | `id` | ✅ | 唯一标识符,反向域名格式 | `com.yourname.plugin` | | `name` | ✅ | 显示名称 | `天气插件` | | `description` | ✅ | 简短描述 | `显示实时天气信息` | | `author` | ✅ | 作者名称 | `张三` | | `version` | ✅ | 版本号(语义化版本) | `1.0.0` | | `apiVersion` | ✅ | SDK API 版本 | `5.0.0` | | `entranceAssembly` | ✅ | 入口程序集文件名 | `MyPlugin.dll` | | `sharedContracts` | ✅ | 共享契约类型列表 | `[]` | | `website` | ❌ | 项目网站 | `https://github.com/...` | | `icon` | ❌ | 图标文件名 | `icon.png` | | `tags` | ❌ | 标签数组 | `["天气", "工具"]` | ### 重要规则 ⚠️ **id 字段规则:** - 只能包含小写字母、数字、点号(`.`) - 必须全局唯一 - 建议使用反向域名格式:`com.yourname.pluginname` - 一经发布不可更改 ⚠️ **version 字段规则:** - 使用语义化版本格式:`主版本.次版本.修订号` - 示例:`1.0.0`、`2.1.3-beta` ⚠️ **apiVersion 字段规则:** - 必须与引用的 SDK 版本兼容 - 当前最新版本:`5.0.0` - 不兼容时宿主将拒绝加载插件 --- ## 🔧 .csproj - 项目文件 定义了项目的构建配置和依赖项。 ### 完整示例 ```xml net10.0 enable enable latest PreserveNewest PreserveNewest ``` ### 关键配置项 | 配置项 | 说明 | 推荐值 | |-------|------|--------| | `TargetFramework` | 目标框架 | `net10.0` | | `LangVersion` | C# 语言版本 | `latest` | | `Nullable` | 可空引用类型 | `enable` | ### SDK 引用 ```xml ``` ⚠️ **版本必须匹配:** - SDK 版本必须与 `plugin.json` 中的 `apiVersion` 兼容 - 建议使用最新稳定版 ### 资源文件配置 确保 `plugin.json` 和本地化文件被正确复制到输出目录: ```xml PreserveNewest PreserveNewest ``` --- ## 🚪 Plugin.cs - 入口类 插件的入口点,负责初始化逻辑。 ### 基本结构 ```csharp using LanMountainDesktop.PluginSdk; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace MyPlugin; [PluginEntrance] public sealed class Plugin : PluginBase { public override void Initialize(HostBuilderContext context, IServiceCollection services) { // 在这里注册组件、设置页面、服务等 // 示例:注册桌面组件 // services.AddPluginDesktopComponent(...); // 示例:注册设置页面 // services.AddPluginSettingsSection(...); } } ``` ### 关键特性 | 特性/类 | 说明 | |--------|------| | `[PluginEntrance]` | 标记插件入口类,必须有且仅有一个 | | `PluginBase` | 插件基类,提供基础功能和日志访问 | | `Initialize` | 初始化方法,宿主启动时调用 | ### Initialize 方法参数 ```csharp public override void Initialize(HostBuilderContext context, IServiceCollection services) ``` | 参数 | 类型 | 说明 | |-----|------|------| | `context` | `HostBuilderContext` | 宿主构建上下文,可访问配置 | | `services` | `IServiceCollection` | 依赖注入服务集合,用于注册组件和服务 | --- ## 🌍 Localization - 本地化文件夹 存放多语言资源文件,支持插件的国际化。 ### 文件夹结构 ``` Localization/ ├── zh-CN.json # 简体中文 ├── zh-TW.json # 繁体中文 ├── en-US.json # 英文(美国) ├── ja-JP.json # 日文 └── ko-KR.json # 韩文 ``` ### 资源文件格式 ```json { "PluginName": "我的插件", "Settings": { "Title": "设置", "RefreshInterval": "刷新间隔" }, "Messages": { "Loading": "加载中...", "Error": "出错了:{0}" } } ``` ### 在代码中使用 ```csharp // 获取本地化字符串 var localizer = serviceProvider.GetRequiredService>(); var pluginName = localizer["PluginName"]; var message = localizer["Messages.Error", errorDetails]; ``` ### 支持的语言代码 | 语言 | 代码 | |-----|------| | 简体中文 | `zh-CN` | | 繁体中文 | `zh-TW` | | 英文 | `en-US` | | 日文 | `ja-JP` | | 韩文 | `ko-KR` | --- ## 📦 构建输出结构 运行 `dotnet build` 后,生成的输出结构: ``` bin/Debug/net10.0/ ├── MyPlugin.dll # 插件程序集 ├── MyPlugin.pdb # 调试符号 ├── plugin.json # 插件清单(复制) ├── Localization/ # 本地化文件夹(复制) │ └── zh-CN.json ├── MyPlugin.laapp # 插件包(由 SDK 自动生成) └── ...(依赖项 DLL) ``` ### .laapp 包结构 `.laapp` 文件本质是一个 ZIP 压缩包,包含: ``` MyPlugin.laapp ├── plugin.json # 清单文件 ├── MyPlugin.dll # 主程序集 ├── Localization/ # 本地化资源 └── ...(其他依赖 DLL) ``` --- ## 🔗 与其他 .NET 项目的区别 | 特性 | 普通 .NET 应用 | 阑山桌面插件 | |-----|---------------|-------------| | 入口点 | `Program.cs` 的 `Main` | `Plugin.cs` 的 `Initialize` | | 运行方式 | 独立运行 | 由宿主加载运行 | | 依赖注入 | 自行配置 | 使用宿主提供的 `IServiceCollection` | | 输出格式 | `.exe` 或 `.dll` | `.laapp` 包 | | 资源访问 | 直接访问 | 通过 SDK API 访问宿主资源 | | 热重载 | 支持 | 不支持(需重启宿主) | --- ## 🎯 最佳实践 ### 项目组织建议 ``` MyPlugin/ ├── plugin.json ├── MyPlugin.csproj ├── Plugin.cs # 入口类(保持简洁) ├── README.md ├── .gitignore ├── Localization/ # 本地化资源 ├── Services/ # 服务类文件夹 │ ├── WeatherService.cs │ └── DataService.cs ├── Views/ # 视图文件夹 │ ├── WeatherWidget.axaml │ ├── WeatherWidget.axaml.cs │ └── SettingsPage.axaml └── ViewModels/ # 视图模型文件夹 ├── WeatherViewModel.cs └── SettingsViewModel.cs ``` ### 文件命名规范 | 类型 | 命名约定 | 示例 | |-----|---------|------| | 入口类 | `Plugin` | `Plugin.cs` | | 组件视图 | `{Name}Widget` | `WeatherWidget.axaml` | | 设置页面 | `{Name}SettingsPage` | `WeatherSettingsPage.axaml` | | 服务类 | `{Name}Service` | `WeatherService.cs` | | 视图模型 | `{Name}ViewModel` | `WeatherViewModel.cs` | --- ## 📚 参考资源 - [Plugin SDK 源码](../../LanMountainDesktop.PluginSdk/) - [插件模板](../../LanMountainDesktop.PluginTemplate/content/) - [02-桌面组件系统](../02-核心概念与原理/02-桌面组件系统.md) - [03-设置系统集成](../02-核心概念与原理/03-设置系统集成.md) --- ## 🎯 下一步 理解了项目结构后,接下来学习: 👉 **[04-调试运行指南](04-调试运行指南.md)** - 掌握调试技巧 或者深入了解核心概念: 👉 **[01-插件生命周期](../02-核心概念与原理/01-插件生命周期.md)** - 理解插件运行机制 --- *最后更新:2026年4月*