{"id":22726997,"url":"https://github.com/zihantype/rudi","last_synced_at":"2025-04-04T08:03:57.002Z","repository":{"id":187163243,"uuid":"676438036","full_name":"ZihanType/rudi","owner":"ZihanType","description":"Rudi - an out-of-the-box dependency injection framework for Rust -- Rudi，一个开箱即用的 Rust 依赖注入框架","archived":false,"fork":false,"pushed_at":"2024-12-31T05:13:48.000Z","size":276,"stargazers_count":87,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-28T07:06:03.441Z","etag":null,"topics":["dependency","dependency-injection","di","ioc"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ZihanType.png","metadata":{"files":{"readme":"README-zh_cn.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-09T07:45:16.000Z","updated_at":"2025-03-02T18:01:20.000Z","dependencies_parsed_at":"2023-08-09T08:08:35.222Z","dependency_job_id":"d38eec76-03b0-46b7-830c-dafae4577ed8","html_url":"https://github.com/ZihanType/rudi","commit_stats":null,"previous_names":["zihantype/rudi"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZihanType%2Frudi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZihanType%2Frudi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZihanType%2Frudi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZihanType%2Frudi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ZihanType","download_url":"https://codeload.github.com/ZihanType/rudi/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247142052,"owners_count":20890652,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dependency","dependency-injection","di","ioc"],"created_at":"2024-12-10T17:08:08.775Z","updated_at":"2025-04-04T08:03:56.980Z","avatar_url":"https://github.com/ZihanType.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rudi\n\n[![Crates.io version](https://img.shields.io/crates/v/rudi.svg?style=flat-square)](https://crates.io/crates/rudi)\n[![docs.rs docs](https://img.shields.io/badge/docs-latest-blue.svg?style=flat-square)](https://docs.rs/rudi)\n\n[English](./README.md) | 简体中文\n\nRudi - 一个开箱即用的 Rust 依赖注入框架。\n\n```rust\nuse rudi::{Context, Singleton, Transient};\n\n// 将 `fn(cx) -\u003e A { A }` 注册为 `A` 的构造函数\n#[derive(Debug)]\n#[Transient]\nstruct A;\n\n#[derive(Debug)]\nstruct B(A);\n\n// 将 `fn(cx) -\u003e B { B::new(cx.resolve::\u003cA\u003e()) }` 注册为 `B` 的构造函数\n#[Transient]\nimpl B {\n    #[di]\n    fn new(a: A) -\u003e B {\n        B(a)\n    }\n}\n\n// 将 `fn(cx) -\u003e C { C::B(cx.resolve::\u003cB\u003e()) }` 注册为 `C` 的构造函数\n#[allow(dead_code)]\n#[Transient]\nenum C {\n    A(A),\n\n    #[di]\n    B(B),\n}\n\n// 将 `fn(cx) -\u003e () { Run(cx.resolve::\u003cB\u003e(), cx.resolve::\u003cC\u003e()) }` 注册为 `()` 的构造函数\n#[Singleton]\nfn Run(b: B, c: C) {\n    println!(\"{:?}\", b);\n    assert!(matches!(c, C::B(_)));\n}\n\nfn main() {\n    // 自动注册所有标记了 `#[Singleton]`、`#[Transient]` 或 `#[SingleOwner]` 属性宏的类型和函数\n    let mut cx = Context::auto_register();\n\n    // 从 `Context` 中获取一个 `()` 的实例，这将会调用 `Run` 函数\n    // 这等价于 `cx.resolve::\u003c()\u003e();`\n    cx.resolve()\n}\n```\n\n## 特性\n\n- 3 种作用域: [`Singleton`](https://docs.rs/rudi/latest/rudi/enum.Scope.html#variant.Singleton), [`Transient`](https://docs.rs/rudi/latest/rudi/enum.Scope.html#variant.Transient) and [`SingleOwner`](https://docs.rs/rudi/latest/rudi/enum.Scope.html#variant.SingleOwner) ([example](./examples/all-scope/))。\n- 异步函数和异步构造器。\n- 可以用在 `struct`、`enum`、`impl block` 和 `function` 上的属性宏。\n- 手动注册和自动注册 (感谢 [inventory](https://github.com/dtolnay/inventory))。\n- 方便的绑定 trait 实现和 trait 对象。\n- 使用类型和名称区分不同的实例。\n- 泛型 (但是必须单态化后手动注册) ([example](./examples/hello-world-with-generic/))。\n- 条件注册 ([example](./examples/condition/))。\n- 引用 (只能是 `Singleton` 和 `SingleOwner` 作用域) ([example](./examples/reference/))。\n\n## 一个更复杂的例子\n\n```rust\nuse std::{fmt::Debug, rc::Rc};\n\nuse rudi::{Context, Singleton, Transient};\n\n// 将 `async fn(cx) -\u003e i32 { 42 }` 注册为 `i32` 的构造函数，并将该 `i32` 类型的实例命名为 `\"number\"`\n#[Singleton(name = \"number\")]\nasync fn Number() -\u003e i32 {\n    42\n}\n\n// 注册 `async fn(cx) -\u003e Foo { Foo { number: cx.resolve_with_name_async(\"number\").await } }` 为 `Foo` 的构造函数，\n// 并将该 `Foo` 类型的实例命名为 `\"foo\"`\n#[derive(Debug, Clone)]\n#[Singleton(async, name = \"foo\")]\nstruct Foo {\n    #[di(name = \"number\")]\n    number: i32,\n}\n\n#[derive(Debug)]\nstruct Bar(Foo);\n\nimpl Bar {\n    fn into_debug(self) -\u003e Rc\u003cdyn Debug\u003e {\n        Rc::new(self)\n    }\n}\n\n// 将 `async fn(cx) -\u003e Bar { Bar::new(cx.resolve_with_name_async(\"foo\").await).await }` 注册为 `Bar` 的构造函数，\n//\n// 将 `Debug` trait 的实现和 `Debug` trait 对象绑定，\n// 这将会注册 `async fn(cx) -\u003e Rc\u003cdyn Debug\u003e { Bar::into_debug(cx.resolve_async().await) }` 为 `Rc\u003cdyn Debug\u003e` 的构造函数。\n#[Transient(binds = [Self::into_debug])]\nimpl Bar {\n    #[di]\n    async fn new(#[di(name = \"foo\")] f: Foo) -\u003e Bar {\n        Bar(f)\n    }\n}\n\n#[Singleton]\nasync fn Run(bar: Bar, debug: Rc\u003cdyn Debug\u003e, #[di(name = \"foo\")] f: Foo) {\n    println!(\"{:?}\", bar);\n    assert_eq!(format!(\"{:?}\", bar), format!(\"{:?}\", debug));\n    assert_eq!(format!(\"{:?}\", bar.0.number), format!(\"{:?}\", f.number));\n}\n\n#[tokio::main]\nasync fn main() {\n    let mut cx = Context::auto_register();\n\n    cx.resolve_async().await\n}\n```\n\n更多例子可以在 [examples](./examples/) 和 [tests](./rudi/tests/) 目录中找到。\n\n## 鸣谢\n\n- [Koin](https://github.com/InsertKoinIO/koin): 本项目的 API 设计和测试用例受到了 Koin 的启发。\n- [inventory](https://github.com/dtolnay/inventory): 本项目使用 inventory 实现了自动注册，使得 Rust 的自动注册变得非常简单。\n\n## 做出贡献\n\n感谢您的帮助改进项目！我们很高兴有您的加入！\n\n## 开源许可\n\n本项目使用 Apache-2.0 和 MIT 双重许可，您可以在以下两个许可之一下自由使用本项目的代码：\n\n- Apache License, Version 2.0,([LICENSE-APACHE](./LICENSE-APACHE) or \u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e)\n- MIT license ([LICENSE-MIT](./LICENSE-MIT) or \u003chttp://opensource.org/licenses/MIT\u003e)\n\n### 贡献\n\n除非您另有明确声明，否则您有意提交以纳入作品的任何贡献（如 Apache-2.0 许可中的定义）均应获得上述双重许可，且无任何附加条款或条件。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzihantype%2Frudi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzihantype%2Frudi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzihantype%2Frudi/lists"}