OLD | NEW |
(Empty) | |
| 1 part of di; |
| 2 |
| 3 typedef dynamic FactoryFn(Injector injector); |
| 4 |
| 5 /** |
| 6 * Visibility determines if the instance in the defining module is visible to |
| 7 * the requesting injector. If true is returned, then the instance from the |
| 8 * defining injector is provided. If false is returned, the injector keeps |
| 9 * walking up the tree to find another visible instance. |
| 10 */ |
| 11 typedef bool Visibility(Injector requesting, Injector defining); |
| 12 |
| 13 typedef Object TypeFactory(factory(Type type, Type annotation)); |
| 14 |
| 15 /** |
| 16 * Module contributes configuration information to an [Injector] by providing a
collection of type |
| 17 * bindings that specify how each type is created. |
| 18 * |
| 19 * When an injector is created, it copies its configuration information from a m
odule. |
| 20 * Defining additional type bindings after an injector is created have no effect
on that injector. |
| 21 * |
| 22 */ |
| 23 class Module { |
| 24 final _providers = <int, Provider>{}; |
| 25 final _childModules = <Module>[]; |
| 26 Map<Type, TypeFactory> _typeFactories = {}; |
| 27 |
| 28 Map<Type, TypeFactory> get typeFactories { |
| 29 if (_childModules.isEmpty) return _typeFactories; |
| 30 |
| 31 var factories = new Map.from(_typeFactories); |
| 32 _childModules.forEach((m) { |
| 33 if (m.typeFactories != null) { |
| 34 factories.addAll(m.typeFactories); |
| 35 } |
| 36 }); |
| 37 return factories; |
| 38 } |
| 39 |
| 40 set typeFactories(Map<Type, TypeFactory> factories) { |
| 41 _typeFactories = factories; |
| 42 } |
| 43 |
| 44 Map<int, Provider> _providersCache; |
| 45 |
| 46 /** |
| 47 * Compiles and returns a map of type bindings by performing depth-first trave
rsal of the |
| 48 * child (installed) modules. |
| 49 */ |
| 50 Map<int, Provider> get bindings { |
| 51 if (_isDirty) { |
| 52 _providersCache = <int, Provider>{}; |
| 53 _childModules.forEach((child) => _providersCache.addAll(child.bindings)); |
| 54 _providersCache.addAll(_providers); |
| 55 } |
| 56 return _providersCache; |
| 57 } |
| 58 |
| 59 /** |
| 60 * Register a binding to a concrete value. |
| 61 * |
| 62 * The [value] is what actually will be injected. |
| 63 */ |
| 64 void value(Type id, value, {Type withAnnotation, Visibility visibility}) { |
| 65 _dirty(); |
| 66 Key key = new Key(id, withAnnotation); |
| 67 _providers[key.id] = new ValueProvider(id, value, visibility); |
| 68 } |
| 69 |
| 70 /** |
| 71 * Registers a binding for a [Type]. |
| 72 * |
| 73 * The default behavior is to simply instantiate the type. |
| 74 * |
| 75 * The following parameters can be specified: |
| 76 * |
| 77 * * [withAnnotation]: Type decorated with additional annotation. |
| 78 * * [implementedBy]: The type will be instantiated using the [new] operator a
nd the |
| 79 * resulting instance will be injected. If no type is provided, then it's |
| 80 * implied that [type] should be instantiated. |
| 81 * * [visibility]: Function which determines fi the requesting injector can se
e the type in the |
| 82 * current injector. |
| 83 */ |
| 84 void type(Type type, {Type withAnnotation, Type implementedBy, Visibility visi
bility}) { |
| 85 _dirty(); |
| 86 Key key = new Key(type, withAnnotation); |
| 87 _providers[key.id] = new TypeProvider( |
| 88 implementedBy == null ? type : implementedBy, visibility); |
| 89 } |
| 90 |
| 91 /** |
| 92 * Register a binding to a factory function. |
| 93 * |
| 94 * The [factoryFn] will be called and all its arguments will get injected. |
| 95 * The result of that function is the value that will be injected. |
| 96 */ |
| 97 void factory(Type id, FactoryFn factoryFn, {Type withAnnotation, |
| 98 Visibility visibility}) { |
| 99 factoryByKey(new Key(id, withAnnotation), factoryFn, |
| 100 visibility: visibility); |
| 101 } |
| 102 |
| 103 void factoryByKey(Key key, FactoryFn factoryFn, {Visibility visibility}) { |
| 104 _dirty(); |
| 105 _providers[key.id] = new FactoryProvider(key.type, factoryFn, visibility); |
| 106 } |
| 107 |
| 108 /** |
| 109 * Installs another module into this module. Bindings defined on this module |
| 110 * take precidence over the installed module. |
| 111 */ |
| 112 void install(Module module) { |
| 113 _childModules.add(module); |
| 114 _dirty(); |
| 115 } |
| 116 |
| 117 _dirty() { |
| 118 _providersCache = null; |
| 119 } |
| 120 |
| 121 bool get _isDirty => |
| 122 _providersCache == null || _childModules.any((m) => m._isDirty); |
| 123 } |
OLD | NEW |