v0.9.0
Pre-release
Pre-release
First public release.
Supported features
- Basic features:
- Binding of a type to an interface
- Inject annotations for constructors
- Binding to a provider
- Binding to an instance/value
- Assisted injection
- Unlike most DI frameworks, most checks are done at compile time, so that errors can be caught early.
Some examples of checks done at compile time:- Checking that all required types are bound (implicitly or explicitly)
- Checking that there are no dependency loops in the bound types.
- The only injection error that can't be detected at compile time is when a type has multiple inconsistent bindings in different modules. This is checked at run-time.
- No code generation. Just include fruit/fruit.h and link with the fruit library.
- Not intrusive. You can bind interfaces and classes without modifying them (e.g. from a third party library that doesn't use Fruit).
- Reduces the need of #includes. The header file of a module only includes the interfaces exposed by the module.
The implementation classes and the interfaces that the module doesn't expose (for example, private interfaces that the client code doesn't need
to know about) don't need to be included. So after changing the binding of a type in a module (as long as the interfaces exposed by the module
remain the same) only the module itself needs to be re-compiled. Yes, any modules that install that module don't need to. This makes
compilation of large projects much faster than an include-all-the-classes-I-need-to-inject approach. - Helps with binary compatibility: as a consequence of the previous point, since the client code doesn't include the implementation classes (not even the header files) if the interfaces exported by the module didn't change the compiled client code is binary compatible with the new implementation.
- No static data. This allows the creation of separate injectors in different parts of a system, which might bind the same type in different ways.
- Conditional injection based on runtime conditions. This allows to decide what to inject based on e.g. flags passed to the executable or an XML file loaded at runtime.
- Note that you don't need special support in Fruit for the way that you use to decide what to inject.
For example, if you'd like to determine the classes to inject based on the result of an RPC to a server sent using a proprietary RPC
framework, you can do this and you don't need to modify Fruit.
- Note that you don't need special support in Fruit for the way that you use to decide what to inject.
- The combination of the previous two features means that at runtime you can decide to create a separate injector with a different configuration.
E.g. think of a web server that receives a notification to reconfigure itself, creates an injector with the new configuration for new requests
and then deletes the old injector when there are no more requests using it, never stopping serving requests.
Still TODO (before v1.0.0):
- Full thread-safety: by implementing eager injection support, multiple threads will be able to share a single injector, with no locking.
- Injection scopes: e.g. will allow to bind a type/value only for the duration of a request, while sharing the non-request-specific bindings across all worker threads (with no locking).
- Multi-bindings: unlike the typical binding when in an injector there's a single binding for each type, multi-bindings allow modules to specify several bindings and injected classes to access the collection of bound instances.
This can be useful for plugin loading/hooks, or to register RPC services in a server.