共享抽象契约
本章节汇总了 Lertaro.PluginSdk 中跨多个接口复用的基础数据模型、只读契约与配置驱动抽象。
1. 检索结果模型 ISearchResult
在 Lertaro 的架构中,插件对搜索结果的观察始终基于只读契约 ISearchResult,禁止直接篡改宿主底层的核心索引数据结构:
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
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 实例,供插件安全调度宿主窗口:
public interface IPluginSearchWindow
{
void LocateInExplorerExternal(string path); // 在资源管理器或配置的文件管理器中高亮定位
void OpenFileOrFolderExternal(string path); // 使用关联程序普通启动
void OpenFileOrFolderAsAdminExternal(string path);// 提权以管理员身份启动
void HideWindow(); // 隐藏当前搜索窗口
}4. 模式驱动的配置体系 IConfigurable
如果你的插件需要提供个性化设置项,只需在插件类上实现 IConfigurable 接口,宿主便会在设置 → 插件 → 配置中自动根据 Schema 渲染出原生美观的表单界面,无需手写任何 XAML:
public interface IConfigurable
{
PluginConfigSchema GetConfigSchema();
}核心字段类型 ConfigFieldType
| 字段类型 | 渲染控件与说明 |
|---|---|
Boolean | 切换开关(Toggle Switch)或复选框。 |
Text | 文本输入框。支持配置 RequireNonEmpty,为空时自动回退为 DefaultValue。 |
| 文本选择 | SelectionStart 和 SelectionLength 用于指定 Text 字段输入对话框中从 0 开始计算的初始选中范围。 |
Integer | 数字微调输入框。支持配置最小值与最大值范围。 |
Choice | 下拉选择框。通过 Choices 或 ChoiceOptions 列表指定可选条目。 |
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 亦支持配置 OnSave 与 OnRollback 生命周期委托:用户点击确定/应用提交时触发 OnSave 执行自定义持久化,取消或回滚时触发 OnRollback 恢复状态。
本地化选择标签
当选项需要使用本地化标签,同时还要保存稳定的配置值时,应使用 ChoiceOptions。PluginConfigChoice.Value 会写入插件设置,LabelKey 会解析为界面显示文本;如果保存值和显示文本相同,继续使用旧的 Choices 列表即可。
new PluginConfigField
{
Key = "DisplayMode",
FieldType = ConfigFieldType.Choice,
DefaultValue = "FriendlyName",
ChoiceOptions =
[
new PluginConfigChoice
{
Value = "FriendlyName",
LabelKey = "DisplayMode_FriendlyName"
}
]
}5. 完整搜索窗口文件结果 IFullSearchFileResultProvider
如果插件需要向完整搜索窗口贡献真实的文件或文件夹行,可以实现 IFullSearchFileResultProvider:
public interface IFullSearchFileResultProvider : IPluginComponent
{
IReadOnlyList<InstantResultItem> GetFileResults(string query, int limit);
}宿主只会在完整搜索窗口的最终渲染阶段调用 GetFileResults。插件不处理当前查询时应返回空列表。返回的每个 InstantResultItem 都必须对应一个实际存在的文件或文件夹,这样完整窗口的路径、大小和类型列才有意义。该组件与插件的即时结果提供者共用同一个启用/禁用开关。
6. 用户配置路径解析 UserPathResolver
当插件接受用户输入或配置中的路径时,应使用 Lertaro.PluginSdk.Helpers.UserPathResolver,在调用文件系统 API 前统一处理环境变量和 Windows Shell 虚拟路径:
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 只有在路径解析为真实且被索引覆盖的文件夹后才能枚举内容。