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

Sauce-0.10.1 A C++ Dependency Injection Framework

- Main Page
- Classes
- Files

- File List

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
21 typedef NewBinding<Dependency, Scope, Constructor, Allocator> NewBinding_;
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
66 typedef ApplyConstructor<InjectParameters, Constructor, Allocator> Inject;
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;
71 typedef DisposalDeleter<Iface, NewBinding_> Deleter;
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_