[−][src]Crate coi_actix_web
This crate provides a simple Dependency Injection framework for actix-web
.
Example
In Cargo.toml
:
[dependencies]
coi = { package = "coi-actix-web", version = "0.4.0" }
actix-web = "2.0.0"
Note that the following example is heavily minified. Files names don't really matter. For a
more involved example, please see the coi-actix-sample
repository.
In your main binary:
use crate::infrastructure::{RepositoryProvider, PoolProvider}; use crate::service::ServiceProvider; use coi::container; use actix_web::{App, HttpServer}; mod traits; mod infrastructure; mod routes; mod service; fn main() { // container! only expects identifiers, so construct this provider outside let postgres_pool = PoolProvider::<NoTls>::new(/* construct actual pool */); // Build your container let container = container! { pool => postgres_pool.singleton, service => ServiceProvider.scoped, repository => RepositoryProvider.scoped, }; HttpServer::new(move || { App::new() // Make sure to assign it to `app_data` and not `data` .app_data(container.clone()) .configure(routes::data::route_config) }) ... }
traits.rs
:
use coi::Inject; // Ensure all of your traits inherit from `Inject` pub trait IService: Inject { ... } pub trait IRepository: Inject { ... }
service.rs
use crate::traits::IService; use coi::Inject; use std::sync::Arc; // derive `Inject` for all structs that will provide the injectable traits. #[derive(Inject)] #[provides(pub dyn IService with Service::new(repository))] struct Service { #[inject] repository: Arc<dyn IRepository>, } impl IService for Service { ... }
Note: See
coi::Inject
for more examples on how to use#[derive(Inject)]
infrastructure.rs
use crate::traits::IRepository; use coi::Inject; use ...::PostgresPool; #[cfg(feature = "notls")] use ...::NoTls; #[cfg(not(feature = "notls"))] use ...::Tls; #[derive(Inject)] #[provides(pub dyn IRepository with Repository::new(pool))] struct Repository { #[cfg(feature = "notls")] #[inject] pool: PostgresPool<NoTls>, #[cfg(not(feature = "notls"))] #[inject] pool: PostgresPool<Tls>, } impl IRepository for Repository { ... } #[derive(Inject)] struct Pool<T> where T: ... { pool: PostgresPool<T> } #[derive(Provide)] #[provides(pub Pool<T> with Pool::new(self.0.pool))] struct PoolProvider<T> where T: ... { pool: PostgresPool<T> } impl<T> PoolProvider<T> where T: ... { fn new(PostgresPool<T>) -> Self { ... } }
routes.rs
use crate::service::IService; use actix_web::{ web::{self, HttpResponse, ServiceConfig}, Responder, }; use coi::inject; use std::sync::Arc; #[inject] async fn get( id: web::Path<i64>, #[inject] service: Arc<dyn IService>, ) -> Result<impl Responder, ()> { let name: String = service.get(*id).await.map_err(|e| log::error!("{}", e))?; Ok(HttpResponse::Ok().json(name)) } #[inject] async fn get_all(#[inject] service: Arc<dyn IService>) -> Result<impl Responder, ()> { let data: Vec<String> = service.get_all().await.map_err(|e| log::error!("{}", e))?; Ok(HttpResponse::Ok().json(data)) } pub fn route_config(config: &mut ServiceConfig) { config.service( web::scope("/data") .route("", web::get().to(get_all)) .route("/", web::get().to(get_all)) .route("/{id}", web::get().to(get)), ); }
Macros
container | A macro to simplify building of |
Structs
Container | A struct that manages all injected types. |
ContainerBuilder | A builder used to construct a |
Registration |
Enums
Error | Errors produced by this crate |
RegistrationKind | Control when |
Traits
Inject | A marker trait for injectable traits and structs. |
Provide | A trait to manage the construction of an injectable trait or struct. |
Type Definitions
Result | Type alias to |
Attribute Macros
inject | The #[inject] proc macro should only be applied to functions that will
be passed to |
Derive Macros
Inject | Generates an impl for |
Provide | There might be some cases where you need to have data passed in with your provider. |