Skip to content

共享抽象契约

本章节汇总了 Lertaro.PluginSdk 中跨多个接口复用的基础数据模型、只读契约与配置驱动抽象。

1. 检索结果模型 ISearchResult

在 Lertaro 的架构中,插件对搜索结果的观察始终基于只读契约 ISearchResult,禁止直接篡改宿主底层的核心索引数据结构:

csharp
namespace Lertaro.PluginSdk;

public interface ISearchResult
{
    string Name { get; }                  // 文件或条目的显示名称(如 "Lertaro.exe")
    string FullPath { get; }              // 绝对物理路径(如 "C:\Program Files\Lertaro\Lertaro.exe")
    string ContextDirectory { get; }      // 所在父级目录路径(如 "C:\Program Files\Lertaro")
    bool IsDir { get; }                   // 是否为目录/文件夹
    bool IsApplication { get; }           // 是否为可执行程序或快捷方式
    FileMetadata Metadata { get; }        // 高性能文件元数据(大小、修改时间等)
    bool[]? GetHighlightMask(string text, string query); // 字符级高亮掩码计算
}

NOTE

ISearchResult.Metadata 包含的数据由宿主底层的 USN / MFT 内存索引直接注入,读取该属性完全不产生任何磁盘 I/O 或 IPC 调用。仅当你需要查询不属于当前结果集的外部路径时,才需要调用 FileMetadataService.GetMetadataAsync

2. 文件元数据结构 FileMetadata

csharp
public readonly record struct FileMetadata(
    long Size,
    DateTime Created,
    DateTime Modified,
    DateTime Accessed
);
  • 时间戳均为本地时间(Local Time)
  • Metadata == default(即各字段均为 0 或 DateTime.MinValue),表示该结果并非由物理文件索引生成(例如由某个即时计算插件动态生成)。
  • 可通过 Metadata.Modified != default 准确区分“元数据不可用”与“大小恰好为 0 字节的合法真实文件”。

3. 宿主安全控制接口 IPluginSearchWindow

当动作执行回调(如 ISearchResultAction.Execute)被触发时,宿主会传入 IPluginSearchWindow 实例,供插件安全调度宿主窗口:

csharp
public interface IPluginSearchWindow
{
    void LocateInExplorerExternal(string path);       // 在资源管理器或配置的文件管理器中高亮定位
    void OpenFileOrFolderExternal(string path);       // 使用关联程序普通启动
    void OpenFileOrFolderAsAdminExternal(string path);// 提权以管理员身份启动
    void HideWindow();                                // 隐藏当前搜索窗口
}

4. 模式驱动的配置体系 IConfigurable

如果你的插件需要提供个性化设置项,只需在插件类上实现 IConfigurable 接口,宿主便会在设置 → 插件 → 配置中自动根据 Schema 渲染出原生美观的表单界面,无需手写任何 XAML:

csharp
public interface IConfigurable
{
    PluginConfigSchema GetConfigSchema();
}

核心字段类型 ConfigFieldType

字段类型渲染控件与说明
Boolean切换开关(Toggle Switch)或复选框。
Text文本输入框。支持配置 RequireNonEmpty,为空时自动回退为 DefaultValue
文本选择SelectionStartSelectionLength 用于指定 Text 字段输入对话框中从 0 开始计算的初始选中范围。
Integer数字微调输入框。支持配置最小值与最大值范围。
Choice下拉选择框。通过 ChoicesChoiceOptions 列表指定可选条目。
Hotkey专属按键录制框。可配置 RequireModifier = true 强制要求必须包含修饰键。
FilePath / FolderPath附带“浏览...”文件/文件夹原生选择器按钮的路径输入框。
StringList支持多行编辑、条目增删排序与自动折行的多行列表框;真实换行仅以视觉标记显示,不会写入配置值。
Group包含子字段列表(SubFields)的可折叠卡片分组。
CustomControl允许插件直接挂载一个自定义的 WPF UIElement 控件实例。
Button渲染操作按钮并调用字段的 OnClick 委托,不存储设置值。

图标字段

将字段的 Schema 键设为 Icon 并使用 Text 类型时,宿主会显示图标预览并支持直接输入 WPF Path Data。粘贴完整 SVG/XML 文档时,宿主会提取并合并所有 <path d> 值,只保存转换后的 WPF Path Data;图标内容无效时会清空并通过主题化错误对话框提示。不需要图标时,空值仍然有效。

PluginConfigSchema 亦支持配置 OnSaveOnRollback 生命周期委托:用户点击确定/应用提交时触发 OnSave 执行自定义持久化,取消或回滚时触发 OnRollback 恢复状态。

本地化选择标签

当选项需要使用本地化标签,同时还要保存稳定的配置值时,应使用 ChoiceOptionsPluginConfigChoice.Value 会写入插件设置,LabelKey 会解析为界面显示文本;如果保存值和显示文本相同,继续使用旧的 Choices 列表即可。

csharp
new PluginConfigField
{
    Key = "DisplayMode",
    FieldType = ConfigFieldType.Choice,
    DefaultValue = "FriendlyName",
    ChoiceOptions =
    [
        new PluginConfigChoice
        {
            Value = "FriendlyName",
            LabelKey = "DisplayMode_FriendlyName"
        }
    ]
}

5. 完整搜索窗口文件结果 IFullSearchFileResultProvider

如果插件需要向完整搜索窗口贡献真实的文件或文件夹行,可以实现 IFullSearchFileResultProvider

csharp
public interface IFullSearchFileResultProvider : IPluginComponent
{
    IReadOnlyList<InstantResultItem> GetFileResults(string query, int limit);
}

宿主只会在完整搜索窗口的最终渲染阶段调用 GetFileResults。插件不处理当前查询时应返回空列表。返回的每个 InstantResultItem 都必须对应一个实际存在的文件或文件夹,这样完整窗口的路径、大小和类型列才有意义。该组件与插件的即时结果提供者共用同一个启用/禁用开关。

6. 用户配置路径解析 UserPathResolver

当插件接受用户输入或配置中的路径时,应使用 Lertaro.PluginSdk.Helpers.UserPathResolver,在调用文件系统 API 前统一处理环境变量和 Windows Shell 虚拟路径:

csharp
string expanded = UserPathResolver.Expand(rawPath);
bool isVirtual = UserPathResolver.IsVirtualPath(expanded);
string resolved = UserPathResolver.Resolve(rawPath);

Expand 会去除首尾空白并展开 %USERPROFILE% 等环境变量。Resolve 会先展开环境变量,再尽可能将 shell:Downloads::{CLSID} 等标记解析为物理路径。对于 shell:AppsFolder 这类没有物理路径的虚拟文件夹,Resolve 会改而返回其规范名 ::{CLSID},使同一文件夹的各种写法彼此相等;该结果仍然是虚拟路径。只有 Shell 完全无法解析的标记才会原样返回。传给文件系统 API 前应使用 IsVirtualPath 检查结果。目录索引 API 只有在路径解析为真实且被索引覆盖的文件夹后才能枚举内容。