Crate minfac

source ·
Expand description

§Lightweight Inversion Of Control

use {minfac::{Registered, ServiceCollection}};

let mut collection = ServiceCollection::new();
collection
    .with::<Registered<u8>>()
    .register(|byte| byte as i16 * 2);
collection.register(|| 1u8);
let provider = collection.build().expect("Configuration is valid");

assert_eq!(Some(2i16), provider.get::<i16>());

§Features

  • Register Types/Traits which are not part of your crate (e.g. std::*). No macros needed.
  • Service registration from separately compiled dynamic libraries. see examples/distributed_simple for more details
  • Transient services are retrieved as T without any additional frills, SharedServices as Arc<T>
  • Inheritance instead of scoped services (Service requests can be delegated to parent ServiceProviders)
  • Service discovery, (provider.get_all::<MyService>() returns an iterator, which lazily generates all registered MyService instances)
  • Fail fast. When building a ServiceProvider all registered services are checked to
    • have all dependencies
    • contain no dependency-cycles
  • Common pitfalls of traditional IOC are prevented by design
    • Singleton services cannot reference scoped services, as scoped services don’t exist
    • Shared services cannot outlive their ServiceProvider (checked at runtime when debug_assertions are enabled)
  • ServiceProvider implements Send+Sync and is threadsafe without using locks

Visit the examples/documentation for more details

§Required Tasks for stable release

✅ Transient services - New instance per request
✅ Shared services - Shared instance per ServiceProvider
✅ Instance services - Shared instance per ServiceProviderFactory

✅ ServiceProviderFactory for creating ServiceProvider’s with minimal overhead
✅ ServiceProviderFactory inherit services from ServiceProvider
⬜ ServiceProviderFactory inherit services from other ServiceProviderFactory

✅ Replaceable strategy for service identification (TypeIds might change between rust versions)
✅ Recursive dependencies check
✅ Missing dependencies check
⬜ Make all structs FFI-Safe
⬜ Remove global Error handler. Use transition from ServiceCollection to ServiceProvider to replace default Error-Hander

Structs§

  • Alias builder is used to register services, which depend on the previous service. This is especially useful, if the previous service contains an anonymous type like a lambda
  • Represents a query for all registered instances of Type T.
  • Collection of constructors for different types of services. Registered constructors are never called in this state. Instances can only be received by a ServiceProvider, which can be created by calling build
  • Lifetime-Errors occur when either a WeakServiceProvider or any shared service outlives the ServiceProvider.
  • Represents a query for the last registered instance of T
  • Type used to retrieve all instances T of a ServiceProvider. Services are built just in time when calling next()
  • ServiceProviders are created directly from ServiceCollections or ServiceProviderFactories and can be used to retrieve services by type. ServiceProviders are final and cannot be modified anßymore. When a ServiceProvider goes out of scope, all related WeakServiceProviders and shared services have to be dropped already. Otherwise dropping the original ServiceProvider results in a call to minfac::ERROR_HANDLER, which panics in std and enabled debug_assertions
  • Performs all checks to build a ServiceProvider on premise that an instance of type T will be available. Therefore, multiple ServiceProvider with a different base can be created very efficiently. This base could e.g. be the ApplicationSettings for the DomainServices or the HttpContext, if one ServiceProvider is generated per HTTP-Request in a WebApi
  • Weak ServiceProviders have the same public API as ServiceProviders, but cannot outlive their original ServiceProvider. If they do, the minfac::ERROR_HANDLER is called.

Enums§

  • Possible errors when calling ServiceCollection::build() or ServiceCollection::build_factory().

Statics§

  • Handles lifetime errors, which cannot be enforced using the type system. This is the case when:

Traits§

  • Represents anything resolvable by a ServiceProvider.

Type Aliases§