**中文** | [**English**](PLUGIN_DEV.md) # BetterLyrics 插件开发指南 🧩 欢迎开发 BetterLyrics 插件!本文档将指导你如何创建一个标准插件,并利用我们的自动化构建工具链,完美解决 .NET 裁剪(Trimming)和依赖冲突问题。 ## 🛠️ 核心机制简介 为了保证插件在主程序发布(Native AOT / Trimmed)后依然稳定运行,我们采用了一套自动化工作流: 1. **智能去重**:编译时,脚本会自动检测主程序已有的 DLL(如 `Newtonsoft.Json`、`BetterLyrics.Core`),并从插件输出目录中剔除,防止版本冲突。 2. **自动分析**:编译后,`PluginAnalyzer` 工具会扫描你的插件,分析缺失的 System 库依赖。 3. **自动注册**:工具会在主程序的 `PluginConfigs` 目录生成配置,利用 `[ModuleInitializer]` 实现插件自动挂载,无需手动写注册代码。 --- ## 🚀 快速开始 ### 1. 创建项目 创建一个 **类库 (Class Library)** 项目。 * **框架**:`.NET 10`。 * **平台**:`net10.0-windows10.0.19041.0`。 ### 2. 配置 `.csproj` (关键步骤) 请将你的 `.csproj` 文件内容替换为以下标准模板。这段配置包含了自动化构建的所有黑科技。 > ⚠️ **注意**:请根据实际文件结构,修改 `` 和 `` 的路径。 ```xml net10.0-windows10.0.26100.0 enable enable 10.0.19041.0 win-x86;win-x64;win-arm64 true false runtime ..\BetterLyrics.WinUI3\BetterLyrics.WinUI3\bin\x64\$(Configuration)\$(TargetFramework)\ ..\PluginAnalyzer\bin\Debug\net10.0\PluginAnalyzer.exe $(TargetDir) BetterLyrics.WinUI3 $(ProjectName) ..\BetterLyrics.WinUI3\BetterLyrics.WinUI3\PluginConfigs\ ``` --- ## 💻 开发流程 ### 1. 引用依赖 你可以像平常一样引用 NuGet 包或第三方 DLL。 * **如果是公共库**(如 `Newtonsoft.Json`):无需做任何事,脚本会自动检测主程序里有没有。如果有,编译时自动剔除,运行时直接使用主程序加载的版本。 * **如果是私有库**(如 `MeCab`):脚本检测到主程序没有,会将其保留在你的插件目录里。 ### 2. 实现接口 在代码中实现 `BetterLyrics.Core` 提供的接口(例如 `ILyricsProvider`)。 ```csharp using BetterLyrics.Core; namespace BetterLyrics.Plugins.MyPlugin; public class MyLyricsSearchPlugin : ILyricsSearchPlugin { public string Id => "your_name.plugin_name"; public string Name => "Plugin display name"; public string Description => "Plugin description."; public string Author => "Your name"; public void Initialize() { // Do something if necessary ... // string? pluginPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); // Do something if necessary ... } public async Task GetLyricsAsync(string title, string artist, string album, double duration) { // Your code here return new LyricsSearchResult(...); } } ``` ### 3. 编译构建 点击 Visual Studio 的 **生成 (Build)**。 观察 **输出 (Output)** 窗口,你会看到自动化工具在工作: 1. `[Smart Trim]`:告诉你哪些库被剔除了(例如 `BetterLyrics.Core.dll`)。 2. `[Analyzer]`:告诉你防裁剪配置文件 (`*_TrimmerRoots.xml`) 已经生成,并成功投递到了主程序的 `PluginConfigs` 文件夹。 --- ## 🔍 原理详解 (Advanced) ### 为什么我看不到生成的配置文件? 生成的配置文件不会在你的插件项目里,而是直接生成到了 **主程序** 的 `PluginConfigs` 文件夹下。 ### 生成了什么? 1. **`MyPlugin_TrimmerRoots.xml`**: 告诉主程序的裁剪器(Trimmer),保留所有你的插件需要用到、但主程序看起来没用到的 System 库。它还包含了一条指令,强制保留生成的 Config 类。 2. **`MyPlugin_TrimmingConfig.cs`**: 包含一个带有 `[ModuleInitializer]` 特性的类。这个类会在主程序启动时 **自动运行**,确保相关的反射元数据被加载,防止运行时崩溃。 ### 依赖关系图 ```mermaid graph TD A[你的插件代码] -->|编译| B(插件 DLL) B -->|智能去重| B B -->|自动化分析| C{PluginAnalyzer} C -->|生成| D[PluginConfigs/MyPlugin_Config.cs] C -->|生成| E[PluginConfigs/MyPlugin_TrimmerRoots.xml] D -->|自动投递| F[主程序项目] E -->|自动投递| F F -->|发布 Publish| G[最终可执行文件] style C fill:#f9f,stroke:#333 style F fill:#bfb,stroke:#333 ``` --- ## ⚠️ 注意事项 1. **编译顺序**: 请务必确保 **主程序 (Host) 至少被编译过一次**(Debug 或 Release 对应模式)。插件的去重脚本依赖于读取主程序的输出目录来进行比对。如果主程序 bin 目录是空的,插件可能会错误地打包所有依赖。 2. **配置一致性**: 如果你在 `Release` 模式下编译插件,确保主程序也是 `Release` 模式。脚本会自动根据 `$(Configuration)` 寻找对应的主程序输出路径。 3. **私有依赖处理**: 如果你引用了一个主程序也有、但你需要**不同版本**的库(这种情况极少见且不推荐),你需要修改 `.csproj` 脚本,移除自动剔除逻辑。 --- ## 🙋‍♂️ 常见问题 **Q: 编译时报错 "命令 ... 已退出,代码为 9009" 或 "不是内部或外部命令"?** A: 这说明构建脚本找不到 `PluginAnalyzer.exe`。请检查 `.csproj` 文件里的 `` 路径配置是否正确。 **Q: 运行时报错 "FileNotFoundException: BetterLyrics.Core"?** A: 这是正常的。插件目录下不应该有 `BetterLyrics.Core.dll`(因为它由主程序提供)。请通过主程序加载插件进行测试,而不是直接运行插件 DLL。 **Q: 发布后插件崩溃,提示 System 库找不到?** A: 请检查主程序的 `PluginConfigs` 目录下是否成功生成了对应的 `*_TrimmerRoots.xml` 文件。如果没有,请尝试重新生成插件项目。