INJECT ====== Inject is intended to be a C++ dependency injection library which: * is header-only Library does not require anything but including its header files * is non-intrusive Any class can be a component. No need to inherit library interfaces, declare mandatory members or include a macro in the class declaration. For a class to be a component all it needs is to have its default-constructor public and functioning. * is macro-less The library does not rely on pre-processing magic for code-generation. No need to declare constructors in a special way or include black-magic macros in your class' body. * is declarative This is similar to the non-intrusive bullet. Using a class as a component is a matter of declaration, which is done separately from the class' declaration, see below for examples * doesn't require code-generation The library relies only on the standard code generation facilities offered by C++98 through the template mechanism. No additional scripts/executables need to be run to get injections functionality to the application. * is very simple to use * fully supports allocation and instantiation through std::allocator * supports up to 10 constructor arguments * can inject to setter methods (two types, see examples) * does not use RTTI * is fully C++98 complaint USAGE & DOCUMENTATION ===================== - start with the quick reference below - see: examples/README for code examples - doxygen: http://www.duvdevani.com/itay/projects/inject/doxygen/ QUICK REFERENCE =============== [All procedural snippets assume ctx is a context instance] Register a new component (mandatory for everything else) -------------------------------------------------------- Declarative: context<>::component<T> comp_decl; or: context<>::component<T> comp_decl("component_name"); Procedural: TBD Where: T - typename of component Register a component as implementing another component ------------------------------------------------------ Declarative: context<>::component<T>::provides<S> impls_decl; Procedural: TBD Where: T - typename of implementing component S - typename of component implemented Select implementing component to use when component is requested ---------------------------------------------------------------- [implementing component must be declared as such (see above)] Declarative: context<>::component<T>::implemented_by<S[, Scope]> impl_decl; Procedural: /* bind T as S implementation */ ctx.bind<T, S[, Scope]>(); or /* bind T as its own implementation */ ctx.bind<T[, Scope]>(); Where: T - typename of component implemented S - typename of implementation component Scope - (optional) implementation scope, one of: scope_none (new instance every time - default) and scope_singleton (same instance every time) Request an instance of a component ---------------------------------- Declarative: context<>::injected<T> p; Procedural: context<>::ptr<T>::type p = ctx.instance<T>(); Where: T - typename of component to get instance of Allocate (and deallocate) a component using a custom allocator -------------------------------------------------------------- Declarative: context<>::component<T>::allocator< MyAllocator<T> > alloc_decl; Procedural: TBD Where: T - typename of component to set allocator for Instantiate a component with a specific constructor --------------------------------------------------- Declarative: context<>::component<T>::constructor<A1[, A2 ... A10]> ctor_decl; Procedural: TBD Where: T - typename of component A1..A10 - typename of components in constructor declaration Inject a component to a C++-style setter during component initialization ------------------------------------------------------------------------ Declarative: context<>::component<T>::assign_setter<S, &T::setter> setter_decl; Procedural: TBD Where: T - typename of component with setter S - typename of component to inject setter - public, non-static method in T with the non-const signature: context<>::ptr<S>::type& setter(); Inject a component to a Java-style setter during component initialization ------------------------------------------------------------------------- Declarative: context<>::component<T>::arg_setter<S, &T::setter> setter_decl; Procedural: TBD Where: T - typename of component with setter S - typename of component to inject setter - public, non-static method in T with the non-const signature: void setter(const context<>::ptr<S>::type& s); BUILDING ======== Inject is a header-only library, which means it does not require building. Just include "inject/inject.h" and compile. To build the unit-tests and example code: - install cmake >= 2.6 - install boost >= 1.47 - in the top-level directory, run: 'cmake -DCMAKE_BUILD_TYPE=Debug .' or '-DCMAKE_BUILD_TYPE=Release .' - make clean && make Unit-tests executable is under: src/tests/inject/unit_tests Example executable is under each example directory. If you have Doxygen installed, you can run 'make doc' at the root folder to generate the API documentation. it should generate to the doxygen/ subfolder. COMPATIBILITY ============= Inject was tested with: - g++ 4.7.1 - clang++ 3.0-6 - MSVC 9 and 10 TODO ==== * Use std::shared_ptr<> when C++11 is available * Use vardiac templates for constructor handling if C++11 is available * Implicit component registration if possible (infer from functional declarations) * thread-safe singletons (with boost or C++11 STL if available) * Implicit cast from ptr<S>::type so it could be assigned to straight setter (i.e. S& setter() and void setter(const S& s), without ptr<S>::type wrapper) * Test with XCode OTHER C++ INJECTION LIBRARIES ============================= * dicpp (https://bitbucket.org/cheez/dicpp/) * cpp-resolver (http://sourceforge.net/projects/cpp-resolver/) * Torgny (http://programmaticallyspeaking.blogspot.com/2010/04/beautiful-dependency-injection-in-c.html) * QtIocContainer (http://sourceforge.net/projects/qtioccontainer/) * hypodermic (http://code.google.com/p/hypodermic/) * sauce (https://github.com/phs/sauce) * wallaroo (https://code.google.com/p/wallaroo/) LICENSE ======= Copyright (c) 2012-2013 Itay Duvdevani All rights reserved. Inject is distributed under the MIT OSI license. For additional info, please refer to: LICENSE or contact itay@duvdevani.com