Sauce-0.10.1: sauce/internal/bindings.h Source File

Sauce-0.10.1 A C++ Dependency Injection Framework

- Main Page
- Classes
- Files

- File List

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
16 namespace sauce {
17
18 class Injector;
19
20 namespace internal {
21
27 template<typename Dependency>
28 sauce::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
49 template<typename ImplicitBindings>
50 class 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
60 public:
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
171 namespace i = ::sauce::internal;
172
173 }
174
175 #endif // SAUCE_INTERNAL_BINDINGS_H_