rust-dix 集成与注册模式
`rust-ef` 与 `rust-dix` DI 容器深度集成,支持构造函数注入和 owned/shared 两种解析模式。
基础注册
use rust_dix::*;
use rust_ef::di::*;
use rust_ef::db_context::DbContext;
use rust_ef_sqlite::DbContextOptionsBuilderExt as _;
let provider = ServiceCollection::new()
.add_dbcontext(|options| {
options.use_sqlite("data source=app.db");
})
.build()
.unwrap();
// 推荐:owned 解析,直接 &mut self 访问
// rust-dix 0.6+: get_owned() 返回 Result<T, RdiError>
let mut ctx: DbContext = provider.get_owned().unwrap();
// 或:共享解析(Arc<DbContext>,&self 访问,同一 scope 内共享)
// use rust_dix::scope::ScopeFactory;
// let scope = provider.create_scope();
// let ctx: Arc<DbContext> = scope.get().unwrap();
在 Handler 中注入
`#[derive(Inject)]` 要求 bare `T` 字段标记 `#[inject(owned)]`(`Arc<T>` 字段标记 `#[inject]`),未标记字段走 `Default::default()`。Handler 方法使用 `&mut self`:
use rust_webapp::*;
use rust_ef::db_context::DbContext;
#[derive(Inject)]
pub struct ListBlogsHandler {
#[inject(owned)]
ctx: DbContext, // bare T + #[inject(owned)] → get_owned()
}
#[inject(scoped)]
#[async_trait]
impl IRequestHandler<ListBlogsRequest, Vec<BlogDto>> for ListBlogsHandler {
async fn handle(&mut self, _req: ListBlogsRequest) -> Result<Vec<BlogDto>> {
let blogs = self.ctx.set::<Blog>().query().to_list().await?;
Ok(blogs.into_iter().map(BlogDto::from).collect())
}
}
Repository 封装模式
pub struct BlogRepository {
ctx: DbContext,
}
impl BlogRepository {
pub async fn list_high_rated(&mut self) -> EFResult<Vec<Blog>> {
let set = self.ctx.set::<Blog>();
let expr = linq!(|b: Blog| b.rating > 4);
set.filter(expr).to_list().await
}
}
设计要点
| 实践 | 说明 | |------|------| | Owned 解析(推荐) | `get_owned()` → `DbContext`,`&mut self` 访问,无需锁 | | Shared 解析 | `scope.get()` → `Arc<DbContext>`,`&self` 访问,同一 scope 内共享 | | 每个请求一个 DbContext | Scoped 生命周期,避免跨请求跟踪污染 | | `#[derive(Inject)]` 显式标记 | bare `T` + `#[inject(owned)]` → owned;`Arc<T>` + `#[inject]` → shared;未标记 → `Default` |
下一节:[多数据库 Keyed 注册](keyed-databases.md)