Sauce-0.10.1
A C++ Dependency Injection Framework
new_binding.h
1 #ifndef SAUCE_INTERNAL_NEW_BINDING_H_
2 #define SAUCE_INTERNAL_NEW_BINDING_H_
3 
4 #include <sauce/injector.h>
5 #include <sauce/memory.h>
6 #include <sauce/named.h>
7 #include <sauce/provider.h>
8 #include <sauce/internal/apply_variadic.h>
9 #include <sauce/internal/binding.h>
10 #include <sauce/internal/key.h>
11 #include <sauce/internal/resolved_binding.h>
12 #include <sauce/internal/self_injector.h>
13 #include <sauce/internal/type_id.h>
14 
15 namespace sauce {
16 namespace internal {
17 
18 template<typename Dependency, typename Scope, typename Constructor, typename Allocator>
19 class NewBinding: public Binding<Dependency, Scope> {
20 
22 
26  struct NewBindingFriend {
27  template<typename T>
28  void validateAcyclicHelper(NewBinding_ const & binding, InjectorPtr injector, TypeIds & ids, std::string name) {
29  binding.template validateAcyclicHelper<T>(injector, ids, name);
30  }
31 
32  template<typename T>
33  typename Key<T>::Ptr injectHelper(NewBinding_ const & binding, InjectorPtr injector, std::string name) {
34  typename Key<T>::Ptr injected;
35  binding.template injectHelper<typename i::Key<T>::Normalized>(injected, injector, name);
36  return injected;
37  }
38  };
39 
40  friend class NewBindingFriend;
41 
42  struct InjectParameters {
43  struct Passed {
44  NewBinding_ const & binding;
45  InjectorPtr & injector;
46 
47  Passed(NewBinding_ const & binding, InjectorPtr & injector):
48  binding(binding), injector(injector) {}
49  };
50 
51  template<typename T, int i>
52  struct Parameter: public NewBindingFriend {
53  typedef typename Key<T>::Ptr Type;
54 
55  template<typename Passed>
56  Type yield(Passed passed) {
57  NewBinding_ const & binding = passed.binding;
58  InjectorPtr & injector = passed.injector;
59  std::string dependencyName = binding.dynamicDependencyNames[i];
60 
61  return this->NewBindingFriend::template injectHelper<T>(binding, injector, dependencyName);
62  }
63  };
64  };
65 
67  typedef typename Inject::Constructed Impl;
68  typedef typename Key<Dependency>::Iface Iface;
69  typedef typename Key<Dependency>::Ptr IfacePtr;
70  typedef sauce::shared_ptr<Impl> ImplPtr;
72 
73  std::vector<std::string> dynamicDependencyNames;
74 
75  struct ValidateAcyclicParameters {
76  struct Passed {
77  NewBinding_ const & binding;
78  InjectorPtr & injector;
79  TypeIds & ids;
80 
81  Passed(NewBinding_ const & binding, InjectorPtr & injector, TypeIds & ids):
82  binding(binding), injector(injector), ids(ids) {}
83  };
84 
85  template<typename T, int i>
86  struct Parameter: public NewBindingFriend {
87  template<typename Passed>
88  void observe(Passed passed) {
89  NewBinding_ const & binding = passed.binding;
90  InjectorPtr & injector = passed.injector;
91  TypeIds & ids = passed.ids;
92  std::string dependencyName = binding.dynamicDependencyNames[i];
93 
94  this->NewBindingFriend::template validateAcyclicHelper<T>(binding, injector, ids, dependencyName);
95  }
96  };
97  };
98 
99  void validateAcyclic(InjectorPtr injector, TypeIds & ids) const {
100  typename ValidateAcyclicParameters::Passed passed(*this, injector, ids);
101  observeConstructor<ValidateAcyclicParameters, Constructor, Allocator>(passed);
102  }
103 
104  void setDynamicDependencyNames(std::vector<std::string> const & dynamicDependencyNames) {
105  this->dynamicDependencyNames = dynamicDependencyNames;
106  this->dynamicDependencyNames.resize(Inject::arity(), unnamed());
107  }
108 
109 public:
110 
111  typedef typename ResolvedBinding<Dependency>::BindingPtr BindingPtr;
112 
113  NewBinding():
114  dynamicDependencyNames(Inject::arity(), unnamed()) {}
115 
123  void inject(IfacePtr & injected, BindingPtr binding, InjectorPtr injector) const {
124  typename InjectParameters::Passed passed(*this, injector);
125  Deleter deleter(sauce::static_pointer_cast<NewBinding_>(binding));
126  ImplPtr impl(applyConstructor<InjectParameters, Constructor, Allocator>(passed), deleter);
127  SelfInjector<Impl> selfInjector;
128  selfInjector.setSelf(impl);
129  typedef Named<Impl, typename i::Key<Dependency>::Name> NormalizedImpl;
130  this->template injectHelper<NormalizedImpl>(impl, injector, this->getName());
131  injected = sauce::static_pointer_cast<Iface>(impl);
132  }
133 
134  void dispose(Iface * iface) const {
135  typedef typename Allocator::template rebind<Impl>::other ImplAllocator;
136  ImplAllocator allocator;
137  Impl * impl = static_cast<Impl *>(iface);
138  impl->~Impl(); // Must not throw
139  allocator.deallocate(impl, 1);
140  }
141 
142 };
143 
144 }
145 
146 namespace i = ::sauce::internal;
147 
148 }
149 
150 #endif // SAUCE_INTERNAL_NEW_BINDING_H_
Definition: apply_variadic.h:49
A smart pointer deleter that diposes with the given disposal.
Definition: disposal_deleter.h:13
If a type requests injection of its own smart pointer, do so.
Definition: self_injector.h:16
Definition: binder.h:317
Wrap dependency requests with Named to choose one of several (statically) named alternatives.
Definition: named.h:12
std::string getName() const
The dynamic name of this binding.
Definition: binding.h:103
void inject(IfacePtr &injected, BindingPtr binding, InjectorPtr injector) const
Inject an Iface.
Definition: new_binding.h:123
Definition: new_binding.h:19
The base class of all actual binding implementations.
Definition: binding.h:22
Definition: binder.h:21
A complete specification of a dependency request.
Definition: key.h:15