Skip to content

CSharp Plugins

雪绫 edited this page Aug 25, 2026 · 4 revisions

C# 与 PCL.Core 引用

当前插件只有 C#/.NET 程序集入口。入口不是某个实现接口的类,而是程序集中的 [Mixin] 类型集合。

项目要求

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <LangVersion>latest</LangVersion>
    <AssemblyName>Example.Plugin</AssemblyName>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="PCL.Core">
      <HintPath>$(PclCorePath)</HintPath>
      <Private>false</Private>
    </Reference>
  </ItemGroup>
</Project>

构建时传入明确路径:

dotnet build -c Release -p:PclCorePath=C:\PCL-Nex\PCL.Core.dll

建议把 PclCorePath 作为 CI 参数,不要把某台开发机的绝对路径提交到公共项目。

目标类型

可直接引用目标类型时使用 Type

[Mixin(typeof(MyPublicTarget))]
internal static class MyTargetMixin
{
}

目标是启动器内部类型或其他插件类型时使用完整名称:

[Mixin("PCL.FormMain", Priority = 1200)]
internal static class FormMainMixin
{
}

Optional = true 表示该 Mixin 类型找不到目标或应用失败时记录警告并继续其他 Mixin:

[Mixin("Optional.Plugin.Type", Optional = true)]
internal static class OptionalIntegrationMixin
{
}

目标方法

操作 Attribute 的第一个参数是目标方法。只有一个同名重载时可只写名称:

[Inject("Run", At = MixinAt.Head)]
private static void BeforeRun()
{
}

存在重载时,使用描述符或 ArgumentTypes

[Inject("Run(System.Int32,System.String)", At = MixinAt.Return)]
private static void AfterRun(CallbackInfo<int> callback)
{
}
[Inject("Run", ArgumentTypes = [typeof(int), typeof(string)], At = MixinAt.Return)]
private static void AfterRun(CallbackInfo<int> callback)
{
}

构造函数使用 .ctor。开放泛型目标和 ref-return 边界注入当前不受支持。

处理器参数绑定

推荐显式标注参数来源:

[Inject("Compute", At = MixinAt.Return, Cancellable = true)]
private static void AfterCompute(
    [This] object instance,
    [Arg(0)] int input,
    [Return] ref int result,
    MethodBase target,
    CallbackInfo<int> callback)
{
    if (input == 0)
        callback.SetReturnValue(42);
}

支持的绑定包括:

  • [This]:目标实例。
  • [Arg(index)]:目标方法参数;ref 参数会尝试写回。
  • [Local(index)]:目标局部变量,需要同时设置 LocalCapture.FailSoftFailHard
  • [Return]:当前返回值。
  • CallbackInfo / CallbackInfo<T>:取消方法或修改返回值。
  • MethodBase / MethodInfo:当前目标方法。
  • object[]:目标参数数组。

未标注参数还会尝试按目标参数名或实例类型绑定,但公共插件应优先使用显式标记,避免目标重构后产生歧义。

静态与实例 Mixin

处理器可以是静态方法,也可以是实例方法。实例 Mixin 需要可由运行时创建的无参构造函数;运行时按目标实例维护 Mixin 实例。仅在确实需要 Shadow 字段或实例状态时使用实例 Mixin。

修改 UI

UI 类型和线程模型属于对应启动器平台的实现契约。插件可以在 Mixin 处理器中替换页面或修改启动器现有控件,但直接引用某个平台 UI 类型的程序集只能发布到该系统组;跨平台插件应把 UI 适配拆到平台专用程序集。处理器应在合适的目标方法和 UI 线程阶段操作真实对象。

需要注意:

  • 在窗口构造前访问控件通常过早。
  • 修改页面字段时应保持启动器后续代码期望的类型,或在原导航逻辑执行前恢复原对象。
  • 事件处理器、计时器和资源由插件自己管理。
  • 启用或禁用插件后应重启启动器。

完整 Attribute 和注入点见 Mixin API 参考注入点与修改操作

Clone this wiki locally