Index: third_party/pkg/di/lib/src/module.dart |
diff --git a/third_party/pkg/di/lib/src/module.dart b/third_party/pkg/di/lib/src/module.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..68f826a15001fc8ca2859a4ce180cedd86e0a4bd |
--- /dev/null |
+++ b/third_party/pkg/di/lib/src/module.dart |
@@ -0,0 +1,123 @@ |
+part of di; |
+ |
+typedef dynamic FactoryFn(Injector injector); |
+ |
+/** |
+ * Visibility determines if the instance in the defining module is visible to |
+ * the requesting injector. If true is returned, then the instance from the |
+ * defining injector is provided. If false is returned, the injector keeps |
+ * walking up the tree to find another visible instance. |
+ */ |
+typedef bool Visibility(Injector requesting, Injector defining); |
+ |
+typedef Object TypeFactory(factory(Type type, Type annotation)); |
+ |
+/** |
+ * Module contributes configuration information to an [Injector] by providing a collection of type |
+ * bindings that specify how each type is created. |
+ * |
+ * When an injector is created, it copies its configuration information from a module. |
+ * Defining additional type bindings after an injector is created have no effect on that injector. |
+ * |
+ */ |
+class Module { |
+ final _providers = <int, Provider>{}; |
+ final _childModules = <Module>[]; |
+ Map<Type, TypeFactory> _typeFactories = {}; |
+ |
+ Map<Type, TypeFactory> get typeFactories { |
+ if (_childModules.isEmpty) return _typeFactories; |
+ |
+ var factories = new Map.from(_typeFactories); |
+ _childModules.forEach((m) { |
+ if (m.typeFactories != null) { |
+ factories.addAll(m.typeFactories); |
+ } |
+ }); |
+ return factories; |
+ } |
+ |
+ set typeFactories(Map<Type, TypeFactory> factories) { |
+ _typeFactories = factories; |
+ } |
+ |
+ Map<int, Provider> _providersCache; |
+ |
+ /** |
+ * Compiles and returns a map of type bindings by performing depth-first traversal of the |
+ * child (installed) modules. |
+ */ |
+ Map<int, Provider> get bindings { |
+ if (_isDirty) { |
+ _providersCache = <int, Provider>{}; |
+ _childModules.forEach((child) => _providersCache.addAll(child.bindings)); |
+ _providersCache.addAll(_providers); |
+ } |
+ return _providersCache; |
+ } |
+ |
+ /** |
+ * Register a binding to a concrete value. |
+ * |
+ * The [value] is what actually will be injected. |
+ */ |
+ void value(Type id, value, {Type withAnnotation, Visibility visibility}) { |
+ _dirty(); |
+ Key key = new Key(id, withAnnotation); |
+ _providers[key.id] = new ValueProvider(id, value, visibility); |
+ } |
+ |
+ /** |
+ * Registers a binding for a [Type]. |
+ * |
+ * The default behavior is to simply instantiate the type. |
+ * |
+ * The following parameters can be specified: |
+ * |
+ * * [withAnnotation]: Type decorated with additional annotation. |
+ * * [implementedBy]: The type will be instantiated using the [new] operator and the |
+ * resulting instance will be injected. If no type is provided, then it's |
+ * implied that [type] should be instantiated. |
+ * * [visibility]: Function which determines fi the requesting injector can see the type in the |
+ * current injector. |
+ */ |
+ void type(Type type, {Type withAnnotation, Type implementedBy, Visibility visibility}) { |
+ _dirty(); |
+ Key key = new Key(type, withAnnotation); |
+ _providers[key.id] = new TypeProvider( |
+ implementedBy == null ? type : implementedBy, visibility); |
+ } |
+ |
+ /** |
+ * Register a binding to a factory function. |
+ * |
+ * The [factoryFn] will be called and all its arguments will get injected. |
+ * The result of that function is the value that will be injected. |
+ */ |
+ void factory(Type id, FactoryFn factoryFn, {Type withAnnotation, |
+ Visibility visibility}) { |
+ factoryByKey(new Key(id, withAnnotation), factoryFn, |
+ visibility: visibility); |
+ } |
+ |
+ void factoryByKey(Key key, FactoryFn factoryFn, {Visibility visibility}) { |
+ _dirty(); |
+ _providers[key.id] = new FactoryProvider(key.type, factoryFn, visibility); |
+ } |
+ |
+ /** |
+ * Installs another module into this module. Bindings defined on this module |
+ * take precidence over the installed module. |
+ */ |
+ void install(Module module) { |
+ _childModules.add(module); |
+ _dirty(); |
+ } |
+ |
+ _dirty() { |
+ _providersCache = null; |
+ } |
+ |
+ bool get _isDirty => |
+ _providersCache == null || _childModules.any((m) => m._isDirty); |
+} |