Sauce-0.10.1
A C++ Dependency Injection Framework
bindings.h
1#ifndef SAUCE_INTERNAL_BINDINGS_H_
2#define SAUCE_INTERNAL_BINDINGS_H_
3
4#include <cassert>
5#include <map>
6#include <utility>
7#include <vector>
8
9#include <sauce/exceptions.h>
10#include <sauce/memory.h>
11#include <sauce/internal/opaque_binding.h>
12#include <sauce/internal/resolved_binding.h>
13#include <sauce/internal/key.h>
14#include <sauce/internal/type_id.h>
15
16namespace sauce {
17
18class Injector;
19
20namespace internal {
21
27template<typename Dependency>
28sauce::shared_ptr<ResolvedBinding<Dependency> > resolve(OpaqueBindingPtr binding) {
29 assert((namedTypeIdOf<Dependency>(binding->getName())) == binding->getKey());
30 return sauce::static_pointer_cast<ResolvedBinding<Dependency> >(binding);
31}
32
49template<typename ImplicitBindings>
50class Bindings {
51 typedef std::map<NamedTypeId, OpaqueBindingPtr> ProvidingBindingMap;
52 typedef std::multimap<NamedTypeId, OpaqueBindingPtr> ModifyingBindingMap;
53 typedef std::multimap<TypeId, OpaqueBindingPtr> ScopeMap;
54 typedef sauce::shared_ptr<Injector> InjectorPtr;
55
56 ProvidingBindingMap providingBindingMap;
57 ModifyingBindingMap modifyingBindingMap;
58 ScopeMap scopeMap;
59
60public:
61
62 Bindings():
63 providingBindingMap(),
64 modifyingBindingMap(),
65 scopeMap() {}
66
70 void put(OpaqueBindingPtr binding) {
71 if (binding->isModifier()) {
72 modifyingBindingMap.insert(std::make_pair(binding->getKey(), binding));
73 } else {
74 providingBindingMap.insert(std::make_pair(binding->getKey(), binding));
75 TypeId scopeKey = binding->getScopeKey();
76 scopeMap.insert(std::make_pair(scopeKey, binding));
77 }
78 }
79
80 template<typename Dependency>
81 sauce::shared_ptr<ResolvedBinding<Dependency> > getProvidingBinding(std::string const name) const {
82 sauce::shared_ptr<ResolvedBinding<Dependency> > binding;
83
84 ProvidingBindingMap::const_iterator i = providingBindingMap.find(namedTypeIdOf<Dependency>(name));
85 if (i == providingBindingMap.end()) {
86 ImplicitBindings implicitBindings;
87 binding = implicitBindings.template getProviding<Dependency>(*this, name);
88 } else {
89 binding = resolve<Dependency>(i->second);
90 }
91
92 return binding;
93 }
94
95 template<typename Dependency>
96 std::vector<sauce::shared_ptr<ResolvedBinding<Dependency> > > getModifierBindings(std::string const name) const {
97 ImplicitBindings implicitBindings;
98 std::vector<sauce::shared_ptr<ResolvedBinding<Dependency> > > bindings =
99 implicitBindings.template getModifyings<Dependency>(*this, name);
100
101 NamedTypeId bindingKey = namedTypeIdOf<Dependency>(name);
102 ModifyingBindingMap::const_iterator i = modifyingBindingMap.lower_bound(bindingKey);
103 ModifyingBindingMap::const_iterator end = modifyingBindingMap.upper_bound(bindingKey);
104
105 for (; i != end; ++i) {
106 OpaqueBindingPtr const & binding = i->second;
107 bindings.push_back(resolve<Dependency>(binding));
108 }
109
110 return bindings;
111 }
112
113 template<typename Dependency>
114 void validateAcyclic(bool validateProviding, InjectorPtr injector, TypeIds & ids, std::string const name) const {
115 typedef sauce::shared_ptr<ResolvedBinding<Dependency> > BindingPtr;
116 BindingPtr binding;
117
118 if (validateProviding) {
119 binding = getProvidingBinding<Dependency>(name);
120 binding->validateAcyclic(injector, ids);
121 }
122
123 typedef std::vector<BindingPtr> BindingPtrs;
124 BindingPtrs bindings = getModifierBindings<Dependency>(name);
125
126 for (typename BindingPtrs::iterator i = bindings.begin(); i != bindings.end(); ++i) {
127 binding = *i;
128 binding->validateAcyclic(injector, ids);
129 }
130 }
131
137 template<typename Dependency>
138 void get(typename Key<Dependency>::Ptr & injected, InjectorPtr injector, std::string const name) const {
139 typedef sauce::shared_ptr<ResolvedBinding<Dependency> > BindingPtr;
140 BindingPtr binding;
141
142 if (injected.get() == NULL) {
143 binding = getProvidingBinding<Dependency>(name);
144 binding->get(injected, binding, injector);
145 }
146
147 typedef std::vector<BindingPtr> BindingPtrs;
148 BindingPtrs bindings = getModifierBindings<Dependency>(name);
149
150 for (typename BindingPtrs::iterator i = bindings.begin(); i != bindings.end(); ++i) {
151 binding = *i;
152 binding->get(injected, binding, injector);
153 }
154 }
155
156 template<typename Scope>
157 void eagerlyInject(InjectorPtr injector) const {
158 TypeId scopeKey = typeIdOf<Scope>();
159 ScopeMap::const_iterator i = scopeMap.lower_bound(scopeKey);
160 ScopeMap::const_iterator end = scopeMap.upper_bound(scopeKey);
161
162 for (; i != end; ++i) {
163 OpaqueBindingPtr const & binding = i->second;
164 binding->eagerlyInject(binding, injector);
165 }
166 }
167};
168
169}
170
171namespace i = ::sauce::internal;
172
173}
174
175#endif // SAUCE_INTERNAL_BINDINGS_H_
A container for bindings.
Definition: bindings.h:50
void put(OpaqueBindingPtr binding)
Insert the given binding.
Definition: bindings.h:70
void get(typename Key< Dependency >::Ptr &injected, InjectorPtr injector, std::string const name) const
Inject the named Dependency.
Definition: bindings.h:138
Attempts to supply a Binding when none is found for a dependency.
Definition: implicit_bindings.h:53
A complete specification of a dependency request.
Definition: key.h:15
A TypeSignature equipped with specific helper methods dealing in the hidden type.
Definition: type_id.h:34