@@ -18,18 +18,21 @@ constructor injection.
1818 - [ autoInjectable()] ( #autoinjectable )
1919 - [ inject()] ( #inject )
2020 - [ injectAll()] ( #injectall )
21+ - [ injectWithTransform()] ( #injectWithTransform )
22+ - [ injectAllWithTransform()] ( #injectAllWithTransform )
2123 - [ scoped()] ( #scoped )
2224 - [ Container] ( #container )
2325 - [ Injection Token] ( #injection-token )
2426 - [ Providers] ( #providers )
2527 - [ Register] ( #register )
2628 - [ Registry] ( #registry )
2729 - [ Resolution] ( #resolution )
30+ - [ Interception] ( #interception )
2831 - [ Child Containers] ( #child-containers )
2932 - [ Clearing Instances] ( #clearing-instances )
3033- [ Circular dependencies] ( #circular-dependencies )
31- - [ The ` delay ` helper function] ( #the-delay-helper-function )
32- - [ Interfaces and circular dependencies] ( #interfaces-and-circular-dependencies )
34+ - [ The ` delay ` helper function] ( #the-delay-helper-function )
35+ - [ Interfaces and circular dependencies] ( #interfaces-and-circular-dependencies )
3336- [ Full examples] ( #full-examples )
3437 - [ Example without interfaces] ( #example-without-interfaces )
3538 - [ Example with interfaces] ( #example-with-interfaces )
@@ -200,22 +203,73 @@ class Bar {
200203}
201204```
202205
206+ ### injectWithTransform
207+
208+ Parameter decorator which allows for a transformer object to take an action on the resolved object
209+ before returning the result.
210+
211+ ``` typescript
212+ class FeatureFlags {
213+ public getFlagValue(flagName : string ): boolean {
214+ // ...
215+ }
216+
217+ class Foo () {}
218+
219+ class FeatureFlagsTransformer implements Transform <FeatureFlags , bool > {
220+ public transform(flags : FeatureFlags , flag : string ) {
221+ return flags .getFlagValue (flag );
222+ }
223+ }
224+
225+ @injectable ()
226+ class MyComponent (foo : Foo , @injectWithTransform (FeatureFlags , FeatureFlagsTransformer , "IsBlahEnabled ") blahEnabled : boolean ){
227+ // ...
228+ }
229+ ` ` `
230+
231+ ### injectAllWithTransform
232+
233+ This parameter decorator allows for array contents to be passed through a transformer. The transformer can return any type, so this
234+ can be used to map or fold an array.
235+
236+ ` ` ` typescript
237+ @injectable
238+ class Foo {
239+ public value;
240+ }
241+
242+ class FooTransform implements Transform <Foo [], string []>{
243+ public transform(foos : Foo []): string []{
244+ return foos .map (f => f .value ));
245+ }
246+ }
247+
248+ @injectable
249+ class Bar {
250+ constructor (@injectAllWithTransform (Foo , FooTransform ) stringArray : string []) {
251+ // ...
252+ }
253+ }
254+ ` ` `
255+
203256### scoped()
204257
205258Class decorator factory that registers the class as a scoped dependency within the global container.
206259
207260#### Available scopes
261+
208262- Transient
209263 - The **default** registration scope, a new instance will be created with each resolve
210264- Singleton
211265 - Each resolve will return the same instance (including resolves from child containers)
212266- ResolutionScoped
213267 - The same instance will be resolved for each resolution of this dependency during a single
214- resolution chain
268+ resolution chain
215269- ContainerScoped
216270 - The dependency container will return the same instance each time a resolution for this dependency
217- is requested. This is similar to being a singleton, however if a child container is made, that child
218- container will resolve an instance unique to it.
271+ is requested. This is similar to being a singleton, however if a child container is made, that child
272+ container will resolve an instance unique to it.
219273
220274#### Usage
221275
@@ -237,7 +291,11 @@ form of a Token/Provider pair, so we need to take a brief diversion to discuss t
237291A token may be either a string, a symbol, a class constructor, or a instance of [ ` DelayedConstructor ` ](#circular-dependencies).
238292
239293` ` ` typescript
240- type InjectionToken <T = any > = constructor <T > | DelayedConstructor <T > | string | symbol ;
294+ type InjectionToken < T = any > =
295+ | constructor <T >
296+ | DelayedConstructor < T >
297+ | string
298+ | symbol;
241299` ` `
242300
243301### Providers
@@ -286,6 +344,7 @@ to the dependency container.
286344
287345We have provided 2 factories for you to use, though any function that matches the ` FactoryFunction <T >` signature
288346can be used as a factory:
347+
289348` ` ` typescript
290349type FactoryFunction < T > = (dependencyContainer : DependencyContainer ) => T ;
291350` ` `
@@ -300,27 +359,27 @@ import {instanceCachingFactory} from "tsyringe";
300359
301360{
302361 token : " SingletonFoo" ;
303- useFactory : instanceCachingFactory <Foo >(c => c .resolve (Foo ))
362+ useFactory : instanceCachingFactory <Foo >(c => c .resolve (Foo ));
304363}
305364` ` `
306365
307366##### predicateAwareClassFactory
308367
309- This factory is used to provide conditional behavior upon resolution. It caches the result by default, but
368+ This factory is used to provide conditional behavior upon resolution. It caches the result by default, but
310369has an optional parameter to resolve fresh each time.
311370
312371` ` ` typescript
313372import {predicateAwareClassFactory } from " tsyringe" ;
314373
315374{
316- token :
317- useFactory : predicateAwareClassFactory <Foo >(
375+ token : useFactory : predicateAwareClassFactory <Foo >(
318376 c => c .resolve (Bar ).useHttps , // Predicate for evaluation
319377 FooHttps , // A FooHttps will be resolved from the container if predicate is true
320378 FooHttp // A FooHttp will be resolved if predicate is false
321- )
379+ );
322380}
323381` ` `
382+
324383#### Token Provider
325384
326385` ` ` TypeScript
@@ -345,6 +404,7 @@ container.register<Baz>("MyBaz", {useValue: new Baz()});
345404` ` `
346405
347406#### Registration options
407+
348408As an optional parameter to ` .register ()` you may provide [ ` RegistrationOptions ` ](./src/types/registration-options.ts)
349409which customize how the registration behaves. See the linked source code for up to date documentation
350410on available options.
@@ -369,7 +429,7 @@ This is useful when you want to [register multiple classes for the same token](#
369429You can also use it to register and declare objects that wouldn't be imported by anything else,
370430such as more classes annotated with ` @registry ` or that are otherwise responsible for registering objects.
371431Lastly you might choose to use this to register 3rd party instances instead of the ` container .register (... )` method.
372- note: if you want this class to be ` @injectable ` you must put the decorator before ` @registry ` , this annotation is not
432+ note: if you want this class to be ` @injectable ` you must put the decorator before ` @registry ` , this annotation is not
373433required though.
374434
375435### Resolution
@@ -394,15 +454,56 @@ class Foo implements Bar {}
394454@injectable()
395455class Baz implements Bar {}
396456
397- @registry ([ // registry is optional, all you need is to use the same token when registering
398- { token: ' Bar' , useToken: Foo }, // can be any provider
399- { token: ' Bar' , useToken: Baz },
457+ @registry([
458+ // registry is optional, all you need is to use the same token when registering
459+ {token: "Bar", useToken: Foo}, // can be any provider
460+ {token: "Bar", useToken: Baz}
400461])
401462class MyRegistry {}
402463
403464const myBars = container.resolveAll<Bar>("Bar"); // myBars type is Bar[]
404465` ` `
405466
467+ ### Interception
468+
469+ Interception allows you to register a callback that will be called before or after the resolution of a specific token .
470+ This callback can be registered to execute only once (to perform initialization , for example ),
471+ on each resolution to do logging, for example .
472+
473+ ` beforeResolution ` is used to take an action before an object is resolved .
474+
475+ ` ` ` typescript
476+ class Bar {}
477+
478+ container.beforeResolution(
479+ Bar,
480+ // Callback signature is (token: InjectionToken<T>, resolutionType: ResolutionType) => void
481+ () => {
482+ console.log("Bar is about to be resolved!");
483+ },
484+ {frequency: "Always"}
485+ );
486+ ` ` `
487+
488+ ` afterResolution ` is used to take an action after the object has been resolved .
489+
490+ ` ` ` typescript
491+ class Bar {
492+ public init(): void {
493+ // ...
494+ }
495+ }
496+
497+ container.afterResolution(
498+ Bar,
499+ // Callback signature is (token: InjectionToken<T>, result: T | T[], resolutionType: ResolutionType)
500+ (_t, result) => {
501+ result.init();
502+ },
503+ {frequency: "Once"}
504+ );
505+ ` ` `
506+
406507### Child Containers
407508
408509If you need to have multiple containers that have disparate sets of registrations, you can create child containers:
@@ -465,28 +566,28 @@ export class Foo {
465566export class Bar {
466567 constructor(public foo: Foo) {}
467568}
468-
469569` ` `
470570
471571Trying to resolve one of the services will end in an error because always one of the constructor will not be fully defined to construct the other one.
472572
473573` ` ` typescript
474- container .resolve (Foo )
574+ container.resolve(Foo);
475575` ` `
576+
476577` ` `
477578Error: Cannot inject the dependency at position #0 of "Foo" constructor. Reason:
478579 Attempted to construct an undefined constructor. Could mean a circular dependency problem. Try using ` delay ` function.
479- ```
480-
481- ### The ` delay ` helper function
580+ ` ` `
581+
582+ ### The ` delay ` helper function
482583
483- The best way to deal with this situation is to do some kind of refactor to avoid the cyclic dependencies. Usually this implies introducing additional services to cut the cycles.
584+ The best way to deal with this situation is to do some kind of refactor to avoid the cyclic dependencies . Usually this implies introducing additional services to cut the cycles .
484585
485- But when refactor is not an option you can use the ` delay ` function helper. The ` delay ` function wraps the constructor in an instance of ` DelayedConstructor ` .
586+ But when refactor is not an option you can use the ` delay ` function helper. The `delay` function wraps the constructor in an instance of `DelayedConstructor`.
486587
487- The * delayed constructor * is a kind of special ` InjectionToken ` that will eventually be evaluated to construct an intermediate proxy object wrapping a factory for the real object.
488-
489- When the proxy object is used for the first time it will construct a real object using this factory and any usage will be forwarded to the real object.
588+ The _delayed constructor_ is a kind of special `InjectionToken` that will eventually be evaluated to construct an intermediate proxy object wrapping a factory for the real object.
589+
590+ When the proxy object is used for the first time it will construct a real object using this factory and any usage will be forwarded to the real object.
490591
491592```typescript
492593@injectable()
@@ -502,13 +603,11 @@ export class Bar {
502603// construction of foo is possible
503604const foo = container .resolve (Foo );
504605
505- // property bar will hold a proxy that looks and acts as a real Bar instance.
606+ // property bar will hold a proxy that looks and acts as a real Bar instance.
506607foo .bar instanceof Bar ; // true
507-
508608` ` `
509609
510- ### Interfaces and circular dependencies
511-
610+ ### Interfaces and circular dependencies
512611
513612We can rest in the fact that a ` DelayedConstructor ` could be used in the same contexts that a constructor and will be handled transparently by tsyringe. Such idea is used in the next example involving interfaces:
514613
@@ -538,7 +637,7 @@ export interface IBar {}
538637export class Bar implements IBar {
539638 constructor (@inject (" IFoo" ) public foo : IFoo ) {}
540639}
541- ```
640+ ` ` `
542641
543642# Full examples
544643
@@ -619,7 +718,9 @@ const client = container.resolve(Client);
619718` ` `
620719
621720## Injecting primitive values (Named injection)
721+
622722Primitive values can also be injected by utilizing named injection
723+
623724` ` ` typescript
624725import {singleton , inject } from " tsyringe" ;
625726
@@ -637,13 +738,15 @@ import {container} from "tsyringe";
637738import {Foo } from " ./foo" ;
638739
639740const str = " test" ;
640- container .register (" SpecialString" , { useValue: str });
741+ container .register (" SpecialString" , {useValue: str });
641742
642743const instance = container .resolve (Foo );
643744` ` `
644745
645746# Non goals
747+
646748The following is a list of features we explicitly plan on not adding:
749+
647750- Property Injection
648751
649752# Contributing
0 commit comments