Skip to content

Extension Points

Ling edited this page Jul 7, 2026 · 4 revisions

通用扩展点

通用扩展点用于让插件向宿主或其他功能贡献对象。它适合那些不应该变成 IPluginHost 顶层专用属性的能力。

例如联机隧道提供者、联机服务、下载源、第三方面板提供者,都可以作为扩展点贡献。

为什么使用扩展点

如果每个插件能力都在 IPluginHost 上新增一个属性,SDK 会很快变成大量专用接口的集合:

Host.LobbyTunnels
Host.SomeOtherFeature
Host.AnotherPluginOnlyApi

通用扩展点改成按名称注册贡献对象:

Host.Extensions.Register(new PluginExtensionDescriptor<TContribution> { ... });

这样宿主只需要维护一套注册机制,具体扩展点由常量和贡献类型约定。

需要的能力

manifest 声明:

"capabilities": ["RegisterExtension"]

C# Attribute 声明:

Capabilities = PluginCapabilities.RegisterExtension

未声明时,context.Host.Extensions 不可用。

注册贡献项

var extensions = context.Host.Extensions
    ?? throw new InvalidOperationException("Extension API is unavailable.");

var registration = extensions.Register(new PluginExtensionDescriptor<IMyContribution>
{
    ExtensionPoint = "com.example:my-extension",
    Id = "default",
    DisplayName = "Example Contribution",
    Order = 100,
    Metadata = new Dictionary<string, string>
    {
        ["kind"] = "example"
    },
    Contribution = new MyContribution()
});

返回的 registration 必须在插件卸载时释放:

public override Task UnloadAsync(CancellationToken cancellationToken = default)
{
    _registration?.Dispose();
    _registration = null;
    return Task.CompletedTask;
}

Descriptor 字段

字段 说明
ExtensionPoint 扩展点标识
Id 贡献项 ID,同一插件同一扩展点内唯一即可
DisplayName 展示名,用于 UI 或日志
Order 排序权重,数值越小越靠前
Metadata 可选元数据
Contribution 实际贡献对象

命名建议

PCL 内置扩展点使用 pcl: 前缀:

pcl:lobby:tunnel-provider
pcl:lobby:service

第三方扩展点建议使用反向域名或明确前缀:

com.example:backup-provider
net.example.launcher:custom-source

内置扩展点

SDK 当前内置:

常量 贡献类型
PluginExtensionPoints.LobbyTunnelProvider pcl:lobby:tunnel-provider ILobbyTunnelProvider
PluginExtensionPoints.LobbyService pcl:lobby:service ILobbyService

联机相关扩展点详见 联机扩展点

何时新增 SDK 强类型接口

如果一个扩展点满足这些条件,可以考虑沉淀为 SDK 中的强类型接口:

  • 多个插件都会实现。
  • 宿主核心功能需要稳定依赖它。
  • 参数、生命周期和错误语义已经稳定。
  • 不再只是某个插件的一次性需求。

在此之前,优先使用 IPluginExtensionApi

Clone this wiki locally