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
15namespace sauce {
16namespace internal {
17
18template<typename Dependency, typename Scope, typename Constructor, typename Allocator>
19class 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
109public:
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
146namespace i = ::sauce::internal;
147
148}
149
150#endif // SAUCE_INTERNAL_NEW_BINDING_H_
Wrap dependency requests with Named to choose one of several (statically) named alternatives.
Definition: named.h:12
Definition: apply_variadic.h:49
The base class of all actual binding implementations.
Definition: binding.h:22
std::string getName() const
The dynamic name of this binding.
Definition: binding.h:103
A smart pointer deleter that diposes with the given disposal.
Definition: disposal_deleter.h:13
A complete specification of a dependency request.
Definition: key.h:15
Definition: new_binding.h:19
void inject(IfacePtr &injected, BindingPtr binding, InjectorPtr injector) const
Inject an Iface.
Definition: new_binding.h:123
If a type requests injection of its own smart pointer, do so.
Definition: self_injector.h:16