component

Attribute Macro component 

Source
#[component]
Expand description

Declares a component that may be used to instantiate types.

§Usage

#[component(...)] may be placed on a trait specifying functions that can later be used to retrieve instances. It may contain definitions of so-called bindings and their dependencies.

The macro results in the generation of a type providing a builder for an implementation of the trait, whose name is prefixed by Dirk.

 use dirk_framework::component; /// Required by `#[component(...)]`

 #[component(
    // ...  (bindings)
 )]
 trait AComponent {
    // ... (binding `fn`s)
 }

 /// Required when using a `Component`
 use dirk_framework::component::Component;
 use dirk_framework::component::builder::Builder;

 /// 1. Via a type-safe builder
 let component = DirkAComponent::builder() // prefix `Dirk` !!!
         // .<...>(...) (provide instance bindings here)
            .build();

 /// 2. ... or using the `create` function, in case no instance bindings are specified
 use dirk_framework::component::StaticComponent;
 let component = DirkAComponent::create(); // prefix `Dirk` !!!

 // Invoke binding `fn`s to retrieve instances, e.g.,
 // let foo = component.<...>();

§Bindings

A binding consists of four parts:

  • a name
  • a binding specifier (e.g., static_bind(...) or cloned_instance_bind(...))
  • a type
  • (optional) dependencies, e.g. [a_binding, b_binding, c_binding]
 #[component(
     name: cloned_instance_bind(&'static str),
     user_service: scoped_bind(UserService),
     auth_service: scoped_bind(AuthService),
     application: static_bind(Application) [name, user_service, auth_service]
 )]
 //  ^         ^  ^         ^ ^         ^  ^                                ^
 //  |_ name  _|  |specifier| |_ type  _|  |____    dependencies        ____|
 trait ApplicationComponent {
     fn user_service(&self) -> std::rc::Rc<std::cell::RefCell<UserService>>;
     fn auth_service(&self) -> std::rc::Rc<std::cell::RefCell<AuthService>>;
     fn application(&self) -> Application;
 }

If a binding is supposed to be queried, a corresponding function needs to be specified in the trait. In case a binding acts only as a dependency for other bindings, such a function can be omitted.

§Static bindings

static_bind(T) may be used to declare a static binding of type T.

§Scoped bindings

scoped_bind(T) may be used to declare a scoped binding of type Rc<RefCell<T>>.

§Singleton bindings

singleton_bind(T) may be used to declare a singleton binding of type Arc<RwLock<T>>.

§Cloned instance bindings

cloned_instance_bind(T) may be used to declare a user-provided binding of type T where T: Clone + 'static, which is cloned every time it is queried or injected.

§Scoped instance bindings

scoped_instance_bind(T) may be used to declare a user-provided binding of type Rc<RefCell<T>> where T: + 'static, such that all queried or injected Rcs point to the same instance.