Skip to content

Commit

Permalink
update wikis and dynamic value typing
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyhallett committed Apr 24, 2021
1 parent 4df7e91 commit e7c7943
Show file tree
Hide file tree
Showing 8 changed files with 25 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/bindings/binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Binding<T> implements interfaces.Binding<T> {
public cache: T | null;

// Cache used to allow BindingType.DynamicValue bindings
public dynamicValue: ((context: interfaces.Context) => T) | null;
public dynamicValue: interfaces.DynamicValue<T> | null;

// The scope mode to be used
public scope: interfaces.BindingScope;
Expand Down
5 changes: 3 additions & 2 deletions src/interfaces/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
namespace interfaces {
export type DynamicValue<T> = (context: interfaces.Context) => T | Promise<T>
export type ContainerResolution<T> = T | Promise<T> | (T | Promise<T>)[]

type AsyncCallback<TCallback> =
Expand Down Expand Up @@ -57,7 +58,7 @@ namespace interfaces {
activated: boolean;
serviceIdentifier: ServiceIdentifier<T>;
constraint: ConstraintFunction;
dynamicValue: ((context: interfaces.Context) => T) | null;
dynamicValue: DynamicValue<T> | null;
scope: BindingScope;
type: BindingType;
implementationType: Newable<T> | null;
Expand Down Expand Up @@ -291,7 +292,7 @@ namespace interfaces {
to(constructor: new (...args: any[]) => T): BindingInWhenOnSyntax<T>;
toSelf(): BindingInWhenOnSyntax<T>;
toConstantValue(value: T): BindingWhenOnSyntax<T>;
toDynamicValue(func: (context: Context) => T | Promise<T>): BindingInWhenOnSyntax<T>;
toDynamicValue(func: DynamicValue<T>): BindingInWhenOnSyntax<T>;
toConstructor<T2>(constructor: Newable<T2>): BindingWhenOnSyntax<T>;
toFactory<T2>(factory: FactoryCreator<T2>): BindingWhenOnSyntax<T>;
toFunction(func: T): BindingWhenOnSyntax<T>;
Expand Down
2 changes: 1 addition & 1 deletion src/syntax/binding_to_syntax.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class BindingToSyntax<T> implements interfaces.BindingToSyntax<T> {
return new BindingWhenOnSyntax<T>(this._binding);
}

public toDynamicValue(func: (context: interfaces.Context) => T): interfaces.BindingInWhenOnSyntax<T> {
public toDynamicValue(func: interfaces.DynamicValue<T>): interfaces.BindingInWhenOnSyntax<T> {
this._binding.type = BindingTypeEnum.DynamicValue;
this._binding.cache = null;
this._binding.dynamicValue = func;
Expand Down
8 changes: 6 additions & 2 deletions wiki/activation_handler.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Activation handler

It is possible to add an activation handler for a type. The activation handler is invoked after a dependency has been resolved and before it is added to the cache (if singleton) and injected. This is useful to keep our dependencies agnostic of the implementation of crosscutting concerns like caching or logging. The following example uses a [proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) to intercept one of the methods (`use`) of a dependency (`Katana`).
It is possible to add an activation handler for a type. The activation handler is invoked after a dependency has been resolved and before it is added to a cache (if singleton or request singleton [see scope](https://github.com/inversify/InversifyJS/blob/master/wiki/scope.md)) and injected. The activation handler will not be invoked if type is resolved from a cache. The activation handler can be synchronous or asynchronous.

Activation handlers are useful to keep our dependencies agnostic of the implementation of crosscutting concerns like caching or logging.

The following example uses a [proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) to intercept one of the methods (`use`) of a dependency (`Katana`).

```ts
interface Katana {
Expand Down Expand Up @@ -57,4 +61,4 @@ There are multiple ways to provide an activation handler
- Adding the handler to the container
- Adding the handler to the binding

When multiple activation handlers are binded to a service identifier, the bindind handlers are called before any others. Any handler defined in a container is called before a handler defined in it's parent container
When multiple activation handlers are binded to a service identifier, the binding handler is called before any others. Then the container handlers are called, starting at the root container and descending the descendant containers stopping at the container with the binding.
6 changes: 4 additions & 2 deletions wiki/deactivation_handler.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Deactivation handler

It is possible to add an activation handler for a type not binded in transient scope. The deactivation handler is invoked before the type is unbinded from the container:
It is possible to add a deactivation handler for a type binded in singleton scope. The handler can be synchronous or asynchronous. The deactivation handler is invoked before the type is unbinded from the container:

```ts
@injectable()
Expand All @@ -24,7 +24,9 @@ It's possible to add a deactivation handler in multiple ways
- Adding the handler to a binding.
- Adding the handler to the class through the [preDestroy decorator](./pre_destroy.md).

Handlers added to the container are the firsts ones to be resolved. Any handler added to a child container is called before the ones added to their parent. Any handler added through the `preDestroy` decorator is called after any handler added to a container or a biding:
Handlers added to the container are the firsts ones to be resolved. Any handler added to a child container is called before the ones added to their parent. Relevant bindings from the container are called next and finally the `preDestroy` method is called. In the example above, relevant bindings are those bindings bound to the unbinded "Destroyable" service identifer.

The example below demonstrates call order.

```ts
let roll = 1;
Expand Down
8 changes: 6 additions & 2 deletions wiki/environment.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,12 @@ This will create the Reflect object as a global.
Most modern JavaScript engines support map but if you need to support old browsers you will need to use a map polyfill (e.g. [es6-map](https://www.npmjs.com/package/es6-map)).

## Promise
[Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) are only required only if you use want to
[inject a provider](https://github.com/inversify/InversifyJS#injecting-a-provider-asynchronous-factory).
[Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) are required if you want to:

[Inject a provider](https://github.com/inversify/InversifyJS/blob/master/wiki/provider_injection.md) or
[inject dynamic values asynchronously](https://github.com/inversify/InversifyJS/blob/master/wiki/value_injection.md).

Handle [post construction](https://github.com/inversify/InversifyJS/blob/master/wiki/post_construct.md) and [activation](https://github.com/inversify/InversifyJS/blob/master/wiki/activation_handler.md), or [pre destroy](https://github.com/inversify/InversifyJS/blob/master/wiki/pre_destroy.md) and [deactivation](https://github.com/inversify/InversifyJS/blob/master/wiki/deactivation_handler.md) asynchronously.

Most modern JavaScript engines support promises but if you need to support old browsers you will need to use a promise polyfill (e.g. [es6-promise](https://github.com/stefanpenner/es6-promise) or [bluebird](https://www.npmjs.com/package/bluebird)).

Expand Down
2 changes: 2 additions & 0 deletions wiki/post_construct.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Its some other cases it gives you a contract that guarantees
that this method will be invoked only once in the lifetime
of the object when used in singleton scope. See the following examples for usage.

The method can be synchronous or asynchronous.


```ts
interface Katana {
Expand Down
2 changes: 2 additions & 0 deletions wiki/value_injection.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ container.bind<Katana>("Katana").toConstantValue(new Katana());
Binds an abstraction to a dynamic value:
```ts
container.bind<Katana>("Katana").toDynamicValue((context: interfaces.Context) => { return new Katana(); });
// a dynamic value can return a promise that will resolve to the value
container.bind<Katana>("Katana").toDynamicValue((context: interfaces.Context) => { return Promise.resolve(new Katana()); });
```

0 comments on commit e7c7943

Please sign in to comment.