Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: third_party/pkg/di/lib/injector.dart

Issue 257423008: Update all Angular libs (run update_all.sh). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/pkg/di/lib/generator.dart ('k') | third_party/pkg/di/lib/mirrors.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 part of di;
2
3 class Injector {
4
5 /**
6 * Name of the injector or null of none is given.
7 */
8 final String name;
9
10 static const List<Type> _PRIMITIVE_TYPES = const <Type>[
11 num, int, double, String, bool
12 ];
13
14 /**
15 * Returns the parent injector or null if root.
16 */
17 final Injector parent;
18
19 Injector _root;
20
21 Map<Type, _Provider> _providers = <Type, _Provider>{};
22
23 final Map<Type, Object> instances = <Type, Object>{};
24
25 final List<Type> resolving = <Type>[];
26
27 final bool allowImplicitInjection;
28
29 Iterable<Type> _typesCache;
30
31 /**
32 * List of all types which the injector can return
33 */
34 Iterable<Type> get _types {
35 if (_typesCache == null) {
36 _typesCache = _providers.keys;
37 }
38 return _typesCache;
39 }
40
41 Injector({List<Module> modules, String name,
42 bool allowImplicitInjection: false})
43 : this.fromParent(modules, null,
44 name: name, allowImplicitInjection: allowImplicitInjection);
45
46 Injector.fromParent(List<Module> modules,
47 Injector this.parent, {this.name, this.allowImplicitInjection}) {
48 _root = parent == null ? this : parent._root;
49 if (modules != null) {
50 modules.forEach((module) {
51 _providers.addAll(module._bindings);
52 });
53 }
54 _providers[Injector] = new _ValueProvider(this);
55 }
56
57 Injector get root => _root;
58
59 Set<Type> get types {
60 var types = new Set.from(_types);
61 var parent = this.parent;
62 while (parent != null) {
63 types.addAll(parent._types);
64 parent = parent.parent;
65 }
66 return types;
67 }
68
69 String _error(message, [appendDependency]) {
70 if (appendDependency != null) {
71 resolving.add(appendDependency);
72 }
73
74 String graph = resolving.join(' -> ');
75
76 resolving.clear();
77
78 return '$message (resolving $graph)';
79 }
80
81 dynamic _getInstanceByType(Type typeName, Injector requester) {
82 _checkTypeConditions(typeName);
83
84 if (resolving.contains(typeName)) {
85 throw new CircularDependencyError(
86 _error('Cannot resolve a circular dependency!', typeName));
87 }
88
89 var providerWithInjector = _getProviderWithInjectorForType(typeName);
90 var provider = providerWithInjector.provider;
91 var injector = providerWithInjector.injector;
92 var visible = provider.visibility != null ?
93 provider.visibility(requester, injector) :
94 _defaultVisibility(requester, injector);
95
96 if (visible && instances.containsKey(typeName)) {
97 return instances[typeName];
98 }
99
100 if (providerWithInjector.injector != this || !visible) {
101 if (!visible) {
102 if (injector.parent == null) {
103 throw new NoProviderError(
104 _error('No provider found for ${typeName}!', typeName));
105 }
106 injector =
107 injector.parent._getProviderWithInjectorForType(typeName).injector;
108 }
109 return injector._getInstanceByType(typeName, requester);
110 }
111
112 var value;
113 try {
114 var strategy = provider.creationStrategy != null ?
115 provider.creationStrategy : _defaultCreationStrategy;
116 value = strategy(requester, injector, () {
117 resolving.add(typeName);
118 var val = provider.get(this, requester, _getInstanceByType, _error);
119 resolving.removeLast();
120 return val;
121 });
122 } catch(e) {
123 resolving.clear();
124 rethrow;
125 }
126
127 // cache the value.
128 providerWithInjector.injector.instances[typeName] = value;
129 return value;
130 }
131
132 /// Returns a pair for provider and the injector where it's defined.
133 _ProviderWithDefiningInjector _getProviderWithInjectorForType(Type typeName) {
134 if (_providers.containsKey(typeName)) {
135 return new _ProviderWithDefiningInjector(_providers[typeName], this);
136 }
137
138 if (parent != null) {
139 return parent._getProviderWithInjectorForType(typeName);
140 }
141
142 if (allowImplicitInjection) {
143 return new _ProviderWithDefiningInjector(
144 new _TypeProvider(typeName), this);
145 }
146
147 throw new NoProviderError(_error('No provider found for '
148 '${typeName}!', typeName));
149 }
150
151 void _checkTypeConditions(Type typeName) {
152 if (_PRIMITIVE_TYPES.contains(typeName)) {
153 throw new NoProviderError(_error('Cannot inject a primitive type '
154 'of $typeName!', typeName));
155 }
156 }
157
158
159 // PUBLIC API
160
161 /**
162 * Get an instance for given token ([Type]).
163 *
164 * If the injector already has an instance for this token, it returns this
165 * instance. Otherwise, injector resolves all its dependencies, instantiate
166 * new instance and returns this instance.
167 *
168 * If there is no binding for given token, injector asks parent injector.
169 *
170 * If there is no parent injector, an implicit binding is used. That is,
171 * the token ([Type]) is instantiated.
172 */
173 dynamic get(Type type) => _getInstanceByType(type, this);
174
175 /**
176 * Create a child injector.
177 *
178 * Child injector can override any bindings by adding additional modules.
179 *
180 * It also accepts a list of tokens that a new instance should be forced.
181 * That means, even if some parent injector already has an instance for this
182 * token, there will be a new instance created in the child injector.
183 */
184 Injector createChild(List<Module> modules,
185 {List<Type> forceNewInstances, String name}) {
186 if (forceNewInstances != null) {
187 Module forceNew = new Module();
188 forceNewInstances.forEach((type) {
189 var providerWithInjector = _getProviderWithInjectorForType(type);
190 var provider = providerWithInjector.provider;
191 forceNew.factory(type,
192 (Injector inj) => provider.get(this, inj, inj._getInstanceByType,
193 inj._error),
194 creation: provider.creationStrategy,
195 visibility: provider.visibility);
196 });
197
198 modules = modules.toList(); // clone
199 modules.add(forceNew);
200 }
201
202 return newFromParent(modules, name);
203 }
204
205 newFromParent(List<Module> modules, String name) {
206 throw new UnimplementedError('This method must be overriden.');
207 }
208
209 Object newInstanceOf(Type type, ObjectFactory factory, Injector requestor,
210 errorHandler(message, [appendDependency])) {
211 throw new UnimplementedError('This method must be overriden.');
212 }
213 }
214
215 class _ProviderWithDefiningInjector {
216 final _Provider provider;
217 final Injector injector;
218 _ProviderWithDefiningInjector(this.provider, this.injector);
219 }
OLDNEW
« no previous file with comments | « third_party/pkg/di/lib/generator.dart ('k') | third_party/pkg/di/lib/mirrors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698