Crate dirk_framework

Source
Expand description

Dirk is a framework for compile-time dependency injection, focusing on usability and developer experience.

§Usage

Dependency Injection using dirk relies on two equally important concepts:

  • Providers (see #[provides(...)]) specify how instances are created
    • static, not wrapped
    • singleton, wrapped in Arc<RwLock<...>> (shared globally)
    • scoped, wrapped in Rc<RefCell<...>> (shared inside an individual component)
  • Components (see #[component(...)]) provide a way to retrieve instances (possibly containing multiple dependencies, specified by so-called bindings)
    • bindings provided via a provider
    • instance bindings, supplied by the user
      • scoped instance, wrapped in Rc<RefCell<...>> (shared inside an individual component)
      • cloned instance, not wrapped (cloned wehenever it is required)

#[use_provides(...)] and #[use_component(...)] may be used to import providers and components in other modules.

§Examples

 use dirk_framework::provides;

 struct UserService {}

 #[provides(scoped_inject)]
 impl UserService {
     fn new() -> Self { UserService { /* ... */ } }    
 }

 struct AuthService {}

 #[provides(scoped_inject)]
 impl AuthService {
     fn new() -> Self { AuthService { /* ... */ } }    
 }

 struct Application {
     user_service: Rc<RefCell<UserService>>,
     auth_service: Rc<RefCell<AuthService>>
 }

 #[provides(static_inject)]
 impl Application{
     fn new(user_service: Rc<RefCell<UserService>>,
             auth_service: Rc<RefCell<AuthService>>) -> Self {
         Application {user_service, auth_service}
     }    
  }

 #[component(
     user_service: scoped_bind(UserService),
     auth_service: scoped_bind(AuthService),
     application: static_bind(Application) [user_service, auth_service]
 )]
 trait ApplicationComponent {
     fn user_service(&self) -> Rc<RefCell<UserService>>;
     fn auth_service(&self) -> Rc<RefCell<AuthService>>;
     fn application(&self) -> Application;
 }

 use dirk_framework::component;
 use dirk_framework::component::{Component, StaticComponent, builder::Builder};

 let component = DirkApplicationComponent::create(); // <- Auto-generated
 let application = component.application();

§Generic Components

Components are even allowed to be generic, as long as no where clause is used and all generic type paramters have lifetime 'static.

 use dirk_framework::component;
 use dirk_framework::component::{Component, StaticComponent, builder::Builder};

 #[component(answer: cloned_instance_bind(T))]
 trait GenericComponent<T: Clone + 'static> {
     fn answer(&self) -> T;
 }

 let component = DirkGenericComponent::builder().answer(42).build();
 assert_eq!(component.answer(), 42);

Modules§

component
Contains data types used by the #[component(...)] macro
provides
Contains data types used by the #[provides] macro

Attribute Macros§

component
Declares a component that may be used to instantiate types.
provides
Annotates an impl block containing a function that provides an instance of a certain type
use_component
May be used to facilitate using components defined in a different module
use_provides
May be used to facilitate injecting or querying types provided in a different module