# teloc
Teloc is simple, compile-time DI framework for Rust inspired by C# Dependency Injection Framework. ## What is DI? [Link to Wikipedia](https://en.wikipedia.org/wiki/Dependency_injection) > Dependency injection (DI) is a technique in which an object receives other objects that it depends on. These other objects are called dependencies. > In the typical "using" relationship the receiving object is called a client and the passed (that is, "injected") object is called a service. > The code that passes the service to the client can be many kinds of things and is called the injector. Instead of the client specifying which service > it will use, the injector tells the client what service to use. The "injection" refers to the passing of a dependency (a service) into the object > (a client) that would use it. ## Highlights - **Compile-time** - teloc uses the powerful rust type system check for the existence of dependencies that have the proper lifetime at compile-time. This means you cannot compile your code if a required dependency has not been registered or if it's lifetime is shorter to what's requested. If your code compiles, that means it runs! - **Zero-overhead** - teloc uses only zero-overhead abstractions such as traits, generics, newtypes and unit types, and compile-time resolving of dependencies, so you don't worry about overhead at runtime. - **Simple API** - teloc provides you a simple API with only one struct and one attribute macro needed for working with library. - **Integration with existing enviroment** - teloc can be used with any existing frameworks like actix-web, warp, rocket. Now there is only support for actix-web as you can see [in the example](/examples/actix_example). ## How to use There are one type can be provider of services: `ServiceProvider`. It used as store for dependencies with `Instance` and `Singleton` lifetimes, and for declaring all dependencies using `.add_*()` methods. It can be forked to create a local scope with local instances. There are four lifetimes for dependencies: 1. `Transient`. Service will be created when resolves. Can depend on dependencies with anything lifetime. 2. `Singleton`. Service will be created once at `ServiceProvider` when it resolved (lazy). Can depend on dependencies with anything lifetime. Cannot depend on services from forked `ServiceProvider` instances. 3. `Instance`. Dependency was created outside of `ServiceProvider` and can be used by any other dependency. How to work: 1. Declare your structs. 2. Create constructors and add `#[inject]` macro on its. 3. Create a `ServiceProvider` object. 4. Add your services and dependencies using `ServiceProvider::add_*` methods. 5. Fork `ServiceProvider` if you need to create local scope. 6. Get service from provider using `.resolve()` method. 7. Work with service. Example: ```rust use teloc::*; // Declare your structs struct ConstService { number: i32, } // #[inject] macro is indicate that dependency can be constructed using this function #[inject] impl ConstService { pub fn new(number: i32) -> Self { ConstService { number } } } // Derive macro can be used when all fields implement `Dependency` trait, but // we recommend using the #[inject] macro it in production code instead. #[derive(Dependency)] struct Controller { number_service: ConstService, } fn main() { // Create `ServiceProvider` struct that store itself all dependencies let sp = ServiceProvider::new() // Add dependency with `Singleton` lifetime. More about lifetimes see above. .add_singleton::Feature | teloc | shaku | waiter_di |
Compile-time checks | Yes | Yes | Yes |
Can be used without dyn traits | Yes | Yes | Yes |
Many service providers in one app | Yes | Yes | No |
Different lifetimes | Yes | Yes | No |