Files
LanMountainDesktop/docs/Plugins develop/01-快速开始/03-插件项目结构详解.md
lincube abfa64b3d7 Avalonia12 (#7)
* ava12升级

* Enable centralized package versioning

Add <Project> and <PropertyGroup> with <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> to Directory.Packages.props to enable centralized package version management across the repository. This allows package versions to be controlled from this single file instead of individual project files.

* Migrate codebase to Avalonia 12 APIs

Apply Avalonia 12 migration changes: replace SystemDecorations with WindowDecorations and remove ExtendClientAreaChromeHints/ExtendClientAreaTitleBarHeightHint usages; update BindingPlugins removal logic (no-op); switch clipboard usage to ClipboardExtensions.SetTextAsync; update Bitmap.CopyPixels calls to the new signature. Replace TextBox.Watermark with PlaceholderText, convert NumberBox styles to FANumberBox and adjust templates, change Checked/Unchecked handlers to IsCheckedChanged, and adapt FluentIcons usages (SymbolIconSource -> FASymbol/FAFont/FluentIcon equivalents). Fix MainWindow partial classes to inherit Window and correct missing variables/fields/usings. Add migration docs/specs/tasks under .trae and include a small TestFluentIcons project for icon testing.

* Migrate to Avalonia 12 and Plugin SDK v5

Upgrade project to the Avalonia 12 baseline and Plugin SDK v5: centralize Avalonia packages, remove legacy WebView.Avalonia usage (use NativeWebView/WebView2 EnvironmentRequested), and update Fluent/Material icon/package usages. Bump multiple package/project versions to 5.0.0 and Avalonia 12.0.1, update plugin template and README/docs to SDK v5, and add PLUGIN_SDK_V5_MIGRATION.md.

Also fix runtime/behavior bugs: make DataLocationResolver use a fixed bootstrap launcher data path and avoid recursive ResolveDataRoot; add legacy-state handling and extraction in OobeStateService; and update component settings tests to reflect migrated storage (DB/backup) and reset cache for test reloads. Various csproj, tests, and docs updated to reflect the migration and ensure build/test compatibility.

* Update icon glyphs and symbol mappings

Replace and refine icon sources across settings pages and controls: many FAFontIconSource glyphs were updated to specific Seagull Fluent Icons codepoints, some FASymbolIconSource usages were replaced with FAFontIconSource, and a number of symbol-to-Symbol enum mappings were adjusted (e.g. "Bell" -> AlertOn, "Shield" -> ShieldLock). Also clarified a comment in SettingsWindow and fixed a trailing newline in StudySettingsPage. Changes standardize icon visuals and bridge FluentIcons glyphs into FluentAvalonia icon sources.

* fix.修复合并产生的问题。
2026-04-29 12:14:29 +08:00

9.2 KiB
Raw Blame History

03-插件项目结构详解

了解插件项目的每个文件和文件夹的作用,是开发高质量插件的基础。本文将详细解析插件项目的完整结构。


📂 项目结构概览

使用模板创建的插件项目结构如下:

MyPlugin/
├── plugin.json                      # 插件清单(必需)
├── MyPlugin.csproj                  # 项目文件(必需)
├── Plugin.cs                        # 入口类(必需)
├── README.md                        # 项目说明(推荐)
├── .gitignore                       # Git忽略文件可选
└── Localization/                    # 本地化文件夹(可选)
    ├── zh-CN.json                   # 中文资源
    └── en-US.json                   # 英文资源

📋 plugin.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.02.1.3-beta

⚠️ apiVersion 字段规则:

  • 必须与引用的 SDK 版本兼容
  • 当前最新版本:5.0.0
  • 不兼容时宿主将拒绝加载插件

🔧 .csproj - 项目文件

定义了项目的构建配置和依赖项。

完整示例

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <LangVersion>latest</LangVersion>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="LanMountainDesktop.PluginSdk" Version="5.0.0" />
  </ItemGroup>

  <ItemGroup>
    <None Update="plugin.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="Localization\**\*.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>

</Project>

关键配置项

配置项 说明 推荐值
TargetFramework 目标框架 net10.0
LangVersion C# 语言版本 latest
Nullable 可空引用类型 enable

SDK 引用

<PackageReference Include="LanMountainDesktop.PluginSdk" Version="5.0.0" />

⚠️ 版本必须匹配:

  • SDK 版本必须与 plugin.json 中的 apiVersion 兼容
  • 建议使用最新稳定版

资源文件配置

确保 plugin.json 和本地化文件被正确复制到输出目录:

<ItemGroup>
  <None Update="plugin.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
  <None Update="Localization\**\*.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

🚪 Plugin.cs - 入口类

插件的入口点,负责初始化逻辑。

基本结构

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<MyWidget>(...);
        
        // 示例:注册设置页面
        // services.AddPluginSettingsSection(...);
    }
}

关键特性

特性/类 说明
[PluginEntrance] 标记插件入口类,必须有且仅有一个
PluginBase 插件基类,提供基础功能和日志访问
Initialize 初始化方法,宿主启动时调用

Initialize 方法参数

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          # 韩文

资源文件格式

{
  "PluginName": "我的插件",
  "Settings": {
    "Title": "设置",
    "RefreshInterval": "刷新间隔"
  },
  "Messages": {
    "Loading": "加载中...",
    "Error": "出错了:{0}"
  }
}

在代码中使用

// 获取本地化字符串
var localizer = serviceProvider.GetRequiredService<IStringLocalizer<MyPlugin>>();
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.csMain Plugin.csInitialize
运行方式 独立运行 由宿主加载运行
依赖注入 自行配置 使用宿主提供的 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

📚 参考资源


🎯 下一步

理解了项目结构后,接下来学习:

👉 04-调试运行指南 - 掌握调试技巧

或者深入了解核心概念:

👉 01-插件生命周期 - 理解插件运行机制


最后更新2026年4月