| 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 |