crates\nfarms-plugin\src\lib.rs¶
源码路径:
crates\nfarms-plugin\src\lib.rs· 44 行
//! cordis 风格的插件内核 —— 服务容器 + 事件总线 + 生命周期。
//!
//! # 为什么要抄 cordis 这一套
//!
//! 这个程序从一开始就是「一页一个功能」的堆叠,堆到第十页时
//! `MainForm.cs` 已经 5,798 行、改任何一处都要重编整个界面。Rust 这版
//! 换了个组织方式:每个功能是一个**插件**,插件只做两件事 ——
//!
//! 1. 向 [Context] 里 `provide` 自己提供的服务;
//! 2. `inject` 自己依赖的服务(依赖没满足就挂着,不报错、不阻塞)。
//!
//! 于是「加一个新功能」= 加一个文件 + 在列表里注册一行,不需要碰别人的代码。
//! 安卓版尤其需要这个:那边只装载骨架里的一小撮插件,以后往 APK 里加东西
//! 就是往注册表里加名字,而不是继续往一个 `match` 里塞分支。
//!
//! # 与 cordis 的对应关系
//!
//! | cordis | 这里 |
//! |---|---|
//! | `ctx.provide(name, value)` / `ctx.get(name)` | [`Context::provide`] / [`Context::get`] |
//! | `ctx.plugin(plugin, config)` | [`Kernel::load`] |
//! | `plugin.inject = ['foo']` | [`Plugin::inject`] |
//! | `ctx.on(event, cb)` / `ctx.emit(event)` | [`Context::on`] / [`Context::emit`] |
//! | `ctx.fork()` / `ctx.scope` | [`Context::fork`] |
//! | `ctx.start()` / `ctx.stop()` | [`Kernel::ready`] / [`Kernel::dispose`] |
//!
//! 两处刻意的简化:
//!
//! * 事件用**枚举**而不是字符串名 + 任意载荷 —— 少一次拼写错误的机会,
//! 而且 `match` 能穷尽检查;
//! * 没有异步。界面本来就是单线程刷新的,引入 async 只会让「插件没加载完
//! 界面先画出来」这种问题变得难查。副作用是 `inject` 的服务必须**同步**
//! 提供 —— 需要联网准备的服务得自己开后台线程,准备好的时候再 `provide`。
#![forbid(unsafe_code)]
mod context;
mod kernel;
mod plugin;
pub use context::{Context, Event, ListenerId};
pub use kernel::{Kernel, PluginRecord, PluginState};
pub use plugin::{Plugin, PluginError, Result};