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 
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_
Definition: binder.h:317
A TypeSignature equipped with specific helper methods dealing in the hidden type. ...
Definition: type_id.h:34
A container for bindings.
Definition: bindings.h:50
Definition: binder.h:21
void put(OpaqueBindingPtr binding)
Insert the given binding.
Definition: bindings.h:70
A complete specification of a dependency request.
Definition: key.h:15
Attempts to supply a Binding when none is found for a dependency.
Definition: implicit_bindings.h:53