Dependency injection for C++ - no macros, no code generation, no common base class
License
z9u2k/inject
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
master
Could not load branches
Nothing to show
Could not load tags
Nothing to show
{{ refName }}
default
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code
-
Clone
Use Git or checkout with SVN using the web URL.
Work fast with our official CLI. Learn more about the CLI.
- Open with GitHub Desktop
- Download ZIP
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
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
* has built-in support for lazy-injection (injection upon first usage as
opposed to construction time)
* 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; // inject at construction time
context<>::injected<T> p(lazy); // injected upon first usage
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
About
Dependency injection for C++ - no macros, no code generation, no common base class
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published