Comparing version
@@ -1,61 +0,84 @@ | ||
import { ParamHandler, PropertyHandler } from "./Handlers"; | ||
import { ServiceMetadata } from "./types/ServiceMetadata"; | ||
import { ObjectType } from "./types/ObjectType"; | ||
import { Handler } from "./types/Handler"; | ||
import { Token } from "./Token"; | ||
import { ServiceIdentifier } from "./types/ServiceIdentifier"; | ||
/** | ||
* Special type that allows to use Function and to known its type as T. | ||
*/ | ||
export declare type ConstructorFunction<T> = { | ||
new (...args: any[]): T; | ||
}; | ||
/** | ||
* Service container. | ||
*/ | ||
export declare class Container { | ||
private static instances; | ||
private static paramHandlers; | ||
private static propertyHandlers; | ||
private static registeredServices; | ||
/** | ||
* Registers a new constructor parameter handler. | ||
* All registered services. | ||
*/ | ||
static registerParamHandler(paramHandler: ParamHandler): void; | ||
private static services; | ||
/** | ||
* Registers a new class property handler. | ||
* All registered handlers. | ||
*/ | ||
static registerPropertyHandler(propertyHandler: PropertyHandler): void; | ||
private static handlers; | ||
/** | ||
* Registers a new handler. | ||
*/ | ||
static registerHandler(handler: Handler): void; | ||
/** | ||
* Registers a new service. | ||
* | ||
* @param name Service name. Optional | ||
* @param type Service class | ||
* @param params Parameters to be sent to constructor on service initialization | ||
*/ | ||
static registerService(name: string, type: Function, params?: any[]): void; | ||
static registerService<T, K extends keyof T>(descriptor: ServiceMetadata<T, K>): void; | ||
/** | ||
* Retrieves the service with the specific name or given type from the service container. | ||
* Optionally parameters can be pass in the case if instance is initialized in the container for the first time. | ||
* Retrieves the service with given name or type from the service container. | ||
* Optionally, parameters can be passed in case if instance is initialized in the container for the first time. | ||
*/ | ||
static get<T>(type: ConstructorFunction<T>, params?: any[]): T; | ||
static get<T>(name: string, params?: any[]): T; | ||
static get<T>(type: ObjectType<T>): T; | ||
/** | ||
* Retrieves the service with given name or type from the service container. | ||
* Optionally, parameters can be passed in case if instance is initialized in the container for the first time. | ||
*/ | ||
static get<T>(id: string): T; | ||
/** | ||
* Retrieves the service with given name or type from the service container. | ||
* Optionally, parameters can be passed in case if instance is initialized in the container for the first time. | ||
*/ | ||
static get<T>(id: Token<T>): T; | ||
/** | ||
* Sets a value for the given type or service name in the container. | ||
*/ | ||
static set(type: Function, value: any): void; | ||
static set(name: string, value: any): void; | ||
static set(type: Function, value: any): Container; | ||
/** | ||
* Sets a value for the given type or service name in the container. | ||
*/ | ||
static set(name: string, value: any): Container; | ||
/** | ||
* Sets a value for the given type or service name in the container. | ||
*/ | ||
static set(token: Token<any>, value: any): Container; | ||
/** | ||
* Provides a set of values to be saved in the container. | ||
*/ | ||
static provide(values: { | ||
name?: string; | ||
type?: Function; | ||
id: ServiceIdentifier; | ||
value: any; | ||
}[]): void; | ||
/** | ||
* Removes services with a given service identifiers (tokens or types). | ||
*/ | ||
static remove(...ids: ServiceIdentifier[]): void; | ||
/** | ||
* Completely resets the container by removing all previously registered services and handlers from it. | ||
*/ | ||
static reset(): void; | ||
/** | ||
* Finds registered service in the with a given service identifier. | ||
*/ | ||
private static findService(identifier); | ||
/** | ||
* Initializes all parameter types for a given target service class. | ||
*/ | ||
private static initializeParams(type, paramTypes); | ||
/** | ||
* Checks if given type is primitive (e.g. string, boolean, number, object). | ||
*/ | ||
private static isTypePrimitive(param); | ||
/** | ||
* Applies all registered handlers on a given target class. | ||
*/ | ||
private static applyPropertyHandlers(target); | ||
private static findInstance(name, type); | ||
private static findInstanceByName(name); | ||
private static findInstanceByType(type); | ||
private static findRegisteredService(name, type); | ||
private static findRegisteredServiceByType(type); | ||
private static findRegisteredServiceByName(name); | ||
private static findParamHandler(type, index); | ||
private static initializeParams(type, params); | ||
private static isTypeSimple(param); | ||
} |
268
Container.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var Token_1 = require("./Token"); | ||
var ServiceNotFoundError_1 = require("./error/ServiceNotFoundError"); | ||
/** | ||
@@ -12,74 +15,80 @@ * Service container. | ||
/** | ||
* Registers a new constructor parameter handler. | ||
* Registers a new handler. | ||
*/ | ||
Container.registerParamHandler = function (paramHandler) { | ||
this.paramHandlers.push(paramHandler); | ||
Container.registerHandler = function (handler) { | ||
this.handlers.push(handler); | ||
}; | ||
/** | ||
* Registers a new class property handler. | ||
* Registers a new service. | ||
*/ | ||
Container.registerPropertyHandler = function (propertyHandler) { | ||
this.propertyHandlers.push(propertyHandler); | ||
Container.registerService = function (descriptor) { | ||
this.services.push(descriptor); | ||
}; | ||
/** | ||
* Registers a new service. | ||
* | ||
* @param name Service name. Optional | ||
* @param type Service class | ||
* @param params Parameters to be sent to constructor on service initialization | ||
* Retrieves the service with given name or type from the service container. | ||
* Optionally, parameters can be passed in case if instance is initialized in the container for the first time. | ||
*/ | ||
Container.registerService = function (name, type, params) { | ||
this.registeredServices.push({ name: name, type: type, params: params }); | ||
}; | ||
Container.get = function (typeOrName, params) { | ||
// normalize parameters | ||
var type, name; | ||
if (typeof typeOrName === "string") { | ||
name = typeOrName; | ||
Container.get = function (identifier) { | ||
// find if service already was registered | ||
var service = this.findService(identifier); | ||
// find if instance of this object already initialized in the container and return it if it is | ||
if (service && service.instance) | ||
return service.instance; | ||
// if named service was requested and its instance was not found plus there is not type to know what to initialize, | ||
// this means service was not pre-registered and we throw an exception | ||
if ((!service || !service.type) && (typeof identifier === "string" || identifier instanceof Token_1.Token)) | ||
throw new ServiceNotFoundError_1.ServiceNotFoundError(identifier); | ||
// at this point we either have type in service registered, either identifier is a target type | ||
var type = service && service.type ? service.type : identifier; | ||
// if service was not found then create a new one and register it | ||
if (!service) { | ||
service = { type: type }; | ||
this.services.push(service); | ||
} | ||
// setup constructor parameters for a newly initialized service | ||
var params = service.paramTypes ? this.initializeParams(type, service.paramTypes) : []; | ||
// if factory is set then use it to create service instance | ||
if (service.factory) { | ||
// filter out non-service parameters from created service constructor | ||
// non-service parameters can be, lets say Car(name: string, isNew: boolean, engine: Engine) | ||
// where name and isNew are non-service parameters and engine is a service parameter | ||
params = params.filter(function (param) { return param !== undefined; }); | ||
if (service.factory instanceof Array) { | ||
// use special [Type, "create"] syntax to allow factory services | ||
// in this case Type instance will be obtained from Container and its method "create" will be called | ||
service.instance = (_a = this.get(service.factory[0]))[service.factory[1]].apply(_a, params); | ||
} | ||
else { | ||
service.instance = service.factory.apply(service, params); | ||
} | ||
} | ||
else { | ||
type = typeOrName; | ||
} | ||
// find if service was already registered | ||
var registeredService = this.findRegisteredService(name, type); | ||
// console.log("registeredService: ", registeredService); | ||
if (registeredService) { | ||
if (!type) | ||
type = registeredService.type; | ||
if (!params) | ||
params = registeredService.params; | ||
} | ||
// find if instance of this object already initialized in the container and return it if it is | ||
var instance = this.findInstance(name, type); | ||
if (instance) | ||
return instance; | ||
// if named service was requested but service was not registered we throw exception | ||
if (!type && name) | ||
throw new Error("Service named " + name + " was not found, probably it was not registered"); | ||
// if params are given we need to go throw each of them and initialize them all properly | ||
if (params) { | ||
params = this.initializeParams(type, params); | ||
params.unshift(null); | ||
service.instance = new (type.bind.apply(type, params))(); | ||
} | ||
// create a new instance of the requested object | ||
var objectInstance = new (type.bind.apply(type, params))(); | ||
this.instances.push({ name: name, type: type, instance: objectInstance }); | ||
this.applyPropertyHandlers(type); | ||
return objectInstance; | ||
return service.instance; | ||
var _a; | ||
}; | ||
Container.set = function (nameOrType, typeOrValue) { | ||
if (typeof nameOrType === "string") { | ||
this.instances.push({ | ||
name: nameOrType, | ||
type: undefined, | ||
instance: typeOrValue | ||
}); | ||
/** | ||
* Sets a value for the given type or service name in the container. | ||
*/ | ||
Container.set = function (identifier, value) { | ||
var service = this.findService(identifier); | ||
if (service) { | ||
service.instance = value; | ||
} | ||
else { | ||
this.instances.push({ | ||
name: undefined, | ||
type: nameOrType, | ||
instance: typeOrValue | ||
}); | ||
var service_1 = { | ||
instance: value | ||
}; | ||
if (identifier instanceof Token_1.Token || typeof identifier === "string") { | ||
service_1.id = identifier; | ||
} | ||
else { | ||
service_1.type = identifier; | ||
} | ||
this.services.push(service_1); | ||
} | ||
return this; | ||
}; | ||
@@ -91,94 +100,93 @@ /** | ||
var _this = this; | ||
values.forEach(function (v) { | ||
if (v.name) { | ||
_this.set(v.name, v.value); | ||
} | ||
else { | ||
_this.set(v.type, v.value); | ||
} | ||
values.forEach(function (v) { return _this.set(v.id, v.value); }); | ||
}; | ||
/** | ||
* Removes services with a given service identifiers (tokens or types). | ||
*/ | ||
Container.remove = function () { | ||
var _this = this; | ||
var ids = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
ids[_i] = arguments[_i]; | ||
} | ||
ids.forEach(function (id) { | ||
var service = _this.findService(id); | ||
if (service) | ||
_this.services.splice(_this.services.indexOf(service), 1); | ||
}); | ||
}; | ||
/** | ||
* Completely resets the container by removing all previously registered services and handlers from it. | ||
*/ | ||
Container.reset = function () { | ||
this.handlers = []; | ||
this.services = []; | ||
}; | ||
// ------------------------------------------------------------------------- | ||
// Private Static Methods | ||
// ------------------------------------------------------------------------- | ||
Container.applyPropertyHandlers = function (target) { | ||
this.propertyHandlers | ||
.filter(function (propertyHandler) { return propertyHandler.target.constructor === target || target.prototype instanceof propertyHandler.target.constructor; }) | ||
.forEach(function (propertyHandler) { | ||
Object.defineProperty(propertyHandler.target, propertyHandler.key, { | ||
enumerable: true, | ||
writable: true, | ||
configurable: true, | ||
value: propertyHandler.getValue() | ||
}); | ||
/** | ||
* Finds registered service in the with a given service identifier. | ||
*/ | ||
Container.findService = function (identifier) { | ||
return this.services.find(function (service) { | ||
if (service.id) | ||
return service.id === identifier; | ||
if (service.type && identifier instanceof Function) | ||
return service.type === identifier || identifier.prototype instanceof service.type; | ||
return false; | ||
}); | ||
}; | ||
Container.findInstance = function (name, type) { | ||
if (name) { | ||
return this.findInstanceByName(name); | ||
} | ||
else if (type) { | ||
return this.findInstanceByType(type); | ||
} | ||
}; | ||
Container.findInstanceByName = function (name) { | ||
return this.instances.reduce(function (found, typeInstance) { | ||
return typeInstance.name === name ? typeInstance.instance : found; | ||
}, undefined); | ||
}; | ||
Container.findInstanceByType = function (type) { | ||
return this.instances.filter(function (instance) { return !instance.name; }).reduce(function (found, typeInstance) { | ||
return typeInstance.type === type ? typeInstance.instance : found; | ||
}, undefined); | ||
}; | ||
Container.findRegisteredService = function (name, type) { | ||
if (name) { | ||
return this.findRegisteredServiceByName(name); | ||
} | ||
else if (type) { | ||
return this.findRegisteredServiceByType(type); | ||
} | ||
}; | ||
Container.findRegisteredServiceByType = function (type) { | ||
return this.registeredServices.filter(function (service) { return !service.name; }).reduce(function (found, service) { | ||
// console.log(service.type, "::", type); | ||
// console.log(type.prototype instanceof service.type); | ||
return service.type === type || type.prototype instanceof service.type ? service : found; | ||
}, undefined); | ||
}; | ||
Container.findRegisteredServiceByName = function (name) { | ||
return this.registeredServices.reduce(function (found, service) { | ||
return service.name === name ? service : found; | ||
}, undefined); | ||
}; | ||
Container.findParamHandler = function (type, index) { | ||
return this.paramHandlers.reduce(function (found, param) { | ||
return param.type === type && param.index === index ? param : found; | ||
}, undefined); | ||
}; | ||
Container.initializeParams = function (type, params) { | ||
/** | ||
* Initializes all parameter types for a given target service class. | ||
*/ | ||
Container.initializeParams = function (type, paramTypes) { | ||
var _this = this; | ||
return params.map(function (param, index) { | ||
var paramHandler = Container.findParamHandler(type, index); | ||
return paramTypes.map(function (paramType, index) { | ||
var paramHandler = _this.handlers.find(function (handler) { return handler.object === type && handler.index === index; }); | ||
if (paramHandler) | ||
return paramHandler.getValue(); | ||
if (param && param.name && !_this.isTypeSimple(param.name)) | ||
return Container.get(param); | ||
return paramHandler.value(); | ||
if (paramType && paramType.name && !_this.isTypePrimitive(paramType.name)) | ||
return Container.get(paramType); | ||
return undefined; | ||
}); | ||
}; | ||
Container.isTypeSimple = function (param) { | ||
/** | ||
* Checks if given type is primitive (e.g. string, boolean, number, object). | ||
*/ | ||
Container.isTypePrimitive = function (param) { | ||
return ["string", "boolean", "number", "object"].indexOf(param.toLowerCase()) !== -1; | ||
}; | ||
// ------------------------------------------------------------------------- | ||
// Private Static Properties | ||
// ------------------------------------------------------------------------- | ||
Container.instances = []; | ||
Container.paramHandlers = []; | ||
Container.propertyHandlers = []; | ||
Container.registeredServices = []; | ||
/** | ||
* Applies all registered handlers on a given target class. | ||
*/ | ||
Container.applyPropertyHandlers = function (target) { | ||
this.handlers.forEach(function (handler) { | ||
if (handler.index) | ||
return; | ||
if (handler.object.constructor !== target && !(target.prototype instanceof handler.object.constructor)) | ||
return; | ||
Object.defineProperty(handler.object, handler.propertyName, { | ||
enumerable: true, | ||
writable: true, | ||
configurable: true, | ||
value: handler.value() | ||
}); | ||
}); | ||
}; | ||
return Container; | ||
}()); | ||
// ------------------------------------------------------------------------- | ||
// Private Static Properties | ||
// ------------------------------------------------------------------------- | ||
/** | ||
* All registered services. | ||
*/ | ||
Container.services = []; | ||
/** | ||
* All registered handlers. | ||
*/ | ||
Container.handlers = []; | ||
exports.Container = Container; | ||
//# sourceMappingURL=Container.js.map |
@@ -0,2 +1,10 @@ | ||
export * from "./decorators/Service"; | ||
export * from "./decorators/Inject"; | ||
export * from "./decorators/Require"; | ||
export { Container } from "./Container"; | ||
export * from "./decorators"; | ||
export { Token } from "./Token"; | ||
export { Handler } from "./types/Handler"; | ||
export { ServiceOptions } from "./types/ServiceOptions"; | ||
export { ServiceIdentifier } from "./types/ServiceIdentifier"; | ||
export { ServiceMetadata } from "./types/ServiceMetadata"; | ||
export { ObjectType } from "./types/ObjectType"; |
@@ -5,6 +5,11 @@ "use strict"; | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__export(require("./decorators/Service")); | ||
__export(require("./decorators/Inject")); | ||
__export(require("./decorators/Require")); | ||
var Container_1 = require("./Container"); | ||
exports.Container = Container_1.Container; | ||
__export(require("./decorators")); | ||
var Token_1 = require("./Token"); | ||
exports.Token = Token_1.Token; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "typedi", | ||
"version": "0.4.3", | ||
"version": "0.5.0", | ||
"description": "Dependency injection for TypeScript", | ||
@@ -21,28 +21,32 @@ "license": "MIT", | ||
"di", | ||
"container", | ||
"di-container", | ||
"typescript", | ||
"typescript-di", | ||
"dependency-injection", | ||
"typescript-require" | ||
"dependency-injection" | ||
], | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@types/chai": "^3.5.1", | ||
"@types/mocha": "^2.2.41", | ||
"@types/node": "^7.0.13", | ||
"@types/sinon": "^2.1.2", | ||
"chai": "^3.4.1", | ||
"del": "^2.2.1", | ||
"es6-shim": "^0.35.1", | ||
"gulp": "^3.9.1", | ||
"gulp-mocha": "^2.2.0", | ||
"gulp-mocha": "^3.0.1", | ||
"gulp-replace": "^0.5.4", | ||
"gulp-shell": "^0.5.1", | ||
"gulp-sourcemaps": "^1.6.0", | ||
"gulp-tslint": "^6.0.1", | ||
"gulp-typescript": "^2.13.6", | ||
"gulpclass": "^0.1.1", | ||
"mocha": "^2.5.3", | ||
"reflect-metadata": "^0.1.3", | ||
"sinon": "^1.17.4", | ||
"sinon-chai": "^2.8.0", | ||
"tslint": "^3.13.0", | ||
"tslint-stylish": "^2.1.0-beta", | ||
"typescript": "^1.8.10", | ||
"typings": "^1.3.1" | ||
"gulp-shell": "^0.6.3", | ||
"gulp-sourcemaps": "^2.6.0", | ||
"gulp-tslint": "^8.0.0", | ||
"gulp-typescript": "^3.1.6", | ||
"gulpclass": "^0.1.2", | ||
"mocha": "^3.2.0", | ||
"reflect-metadata": "^0.1.10", | ||
"sinon": "^2.1.0", | ||
"sinon-chai": "^2.9.0", | ||
"ts-node": "^3.0.2", | ||
"tslint": "^5.1.0", | ||
"tslint-stylish": "^2.1.0", | ||
"typescript": "^2.2.2" | ||
}, | ||
@@ -49,0 +53,0 @@ "scripts": { |
209
README.md
# TypeDI | ||
Dependency injection tool for Typescript. | ||
Simple yet powerful dependency injection tool for Typescript. | ||
@@ -12,14 +12,24 @@ ## Installation | ||
2. Use [typings](https://github.com/typings/typings) to install all required definition dependencies. | ||
2. You also need to install [reflect-metadata](https://www.npmjs.com/package/reflect-metadata) package. | ||
`typings install` | ||
`npm install reflect-metadata --save` | ||
and import it somewhere in the global place of your app (for example in `app.ts`): | ||
`import "reflect-metadata";` | ||
3. ES6 features are used, so you may want to install [es6-shim](https://github.com/paulmillr/es6-shim) too. You also | ||
need to install [reflect-metadata](https://www.npmjs.com/package/reflect-metadata) package. | ||
3. You may need to install node typings: | ||
`npm install es6-shim --save` | ||
`npm install reflect-metadata --save` | ||
`npm install @types/node --save` | ||
if you are building nodejs app, you may want to `require("es6-shim");` and `require("reflect-metadata")` in your app. | ||
4. Also make sure you are using TypeScript compiler version > **2.1** | ||
and you have enabled following settings in `tsconfig.json`: | ||
```json | ||
"lib": ["es6"], | ||
"emitDecoratorMetadata": true, | ||
"experimentalDecorators": true, | ||
``` | ||
## Usage | ||
@@ -46,4 +56,5 @@ | ||
```javascript | ||
import {Container, Inject} from "typedi"; | ||
import {Container, Inject, Service} from "typedi"; | ||
@Service() | ||
class BeanFactory { | ||
@@ -54,2 +65,3 @@ create() { | ||
@Service() | ||
class SugarFactory { | ||
@@ -60,2 +72,3 @@ create() { | ||
@Service() | ||
class WaterFactory { | ||
@@ -66,2 +79,3 @@ create() { | ||
@Service() | ||
class CoffeeMaker { | ||
@@ -95,2 +109,3 @@ | ||
@Service() | ||
class BeanFactory { | ||
@@ -101,2 +116,3 @@ create() { | ||
@Service() | ||
class SugarFactory { | ||
@@ -107,2 +123,3 @@ create() { | ||
@Service() | ||
class WaterFactory { | ||
@@ -139,6 +156,6 @@ create() { | ||
> note: Your classes may not to have `@Service` decorator to use it with Container, however its recommended to add | ||
`@Service` decorator to all classes you are using with container, especially if you class injects other | ||
services | ||
`@Service` decorator to all classes you are using with container, because without `@Service` decorator applied | ||
constructor injection may not work properly in your classes. | ||
### Extra feature: Injecting third-party dependencies *(experimental)* | ||
### Injecting third-party dependencies *(experimental)* | ||
@@ -153,10 +170,10 @@ Also you can inject a modules that you want to `require`: | ||
private gulp: any; // you can use type if you have definition for this package | ||
private logger: any; // you can use type if you have definition for this package | ||
constructor(@Require("gulp") gulp: any) { | ||
this.gulp = gulp; // the same if you do this.gulp = require("gulp") | ||
constructor(@Require("logger") logger: any) { | ||
this.logger = logger; // the same if you do this.logger = require("logger") | ||
} | ||
make() { | ||
console.log(this.gulp); // here you get console.logged gulp package =) | ||
console.log(this.logger); // here you get console.logged logger package =) | ||
} | ||
@@ -225,2 +242,100 @@ } | ||
### Services with token name | ||
You can use a services with a `Token` instead of name or target class. | ||
In this case you can use type safe interface-based services. | ||
```javascript | ||
import {Container, Service, Inject, Token} from "typedi"; | ||
export interface Factory { | ||
create(): void; | ||
} | ||
export const FactoryService = new Token<Factory>(); | ||
@Service(FactoryService) | ||
export class BeanFactory implements Factory { | ||
create() { | ||
} | ||
} | ||
@Service() | ||
export class CoffeeMaker { | ||
private factory: Factory; | ||
constructor(@Inject(FactoryService) factory: Factory) { | ||
this.factory = factory; | ||
} | ||
make() { | ||
this.factory.create(); | ||
} | ||
} | ||
let coffeeMaker = Container.get(CoffeeMaker); | ||
coffeeMaker.make(); | ||
let factory = Container.get(FactoryService); | ||
factory.create(); | ||
``` | ||
### Using factory function to create service | ||
You can create your services with the container using factory functions. | ||
This way, service instance will be created by calling your factory function instead of | ||
instantiating a class directly. | ||
```javascript | ||
import {Container, Service} from "typedi"; | ||
function createCar() { | ||
return new Car("V8"); | ||
} | ||
@Service({ factory: createCar }) | ||
class Car { | ||
constructor (public engineType: string) { | ||
} | ||
} | ||
// Getting service from the container. | ||
// Service will be created by calling the specified factory function. | ||
const car = Container.get(Car); | ||
console.log(car.engineType); // > "V8" | ||
``` | ||
### Using factory class to create service | ||
You can also create your services using factory classes. | ||
This way, service instance will be created by calling given factory service's method factory instead of | ||
instantiating a class directly. | ||
```javascript | ||
import {Container, Service} from "typedi"; | ||
@Service() | ||
class CarFactory { | ||
constructor(public logger: LoggerService) { | ||
} | ||
create() { | ||
return new Car("BMW", this.logger); | ||
} | ||
} | ||
@Service({ factory: [CarFactory, "create"] }) | ||
class Car { | ||
constructor(public model: string, public logger: LoggerInterface) { | ||
} | ||
} | ||
``` | ||
### Providing values to the container | ||
@@ -234,8 +349,8 @@ | ||
// or alternatively: | ||
// or | ||
Container.provide([ | ||
{ name: "bean.factory", type: BeanFactory, value: new FakeBeanFactory() }, | ||
{ name: "sugar.factory", type: SugarFactory, value: new FakeSugarFactory() }, | ||
{ name: "water.factory", type: WaterFactory, value: new FakeWaterFactory() } | ||
{ id: "bean.factory", value: new FakeBeanFactory() }, | ||
{ id: "sugar.factory", value: new FakeSugarFactory() }, | ||
{ id: "water.factory", value: new FakeWaterFactory() } | ||
]); | ||
@@ -265,3 +380,3 @@ ``` | ||
This code will not work, because Engine has a reference to Car, and Car has a reference to Engine. | ||
One of them will be undefined and it will cause an errors. To fix them you need to specify a type in a function like this: | ||
One of them will be undefined and it cause errors. To fix them you need to specify a type in a function this way: | ||
@@ -309,2 +424,54 @@ ```javascript | ||
### Custom decorators | ||
You can create your own decorators which will inject your given values for your service dependencies. | ||
For example: | ||
```javascript | ||
// Logger.ts | ||
export function Logger() { | ||
return function(object: Object, propertyName: string, index?: number) { | ||
const logger = new ConsoleLogger(); | ||
Container.registerHandler({ object, propertyName, index, value: () => logger }); | ||
}; | ||
} | ||
// LoggerInterface.ts | ||
export interface LoggerInterface { | ||
log(message: string): void; | ||
} | ||
// ConsoleLogger.ts | ||
import {LoggerInterface} from "./LoggerInterface"; | ||
export class ConsoleLogger implements LoggerInterface { | ||
log(message: string) { | ||
console.log(message); | ||
} | ||
} | ||
// UserRepository.ts | ||
@Service() | ||
export class UserRepository { | ||
constructor(@Logger() private logger: LoggerInterface) { | ||
} | ||
save(user: User) { | ||
this.logger.log(`user ${user.firstName} ${user.secondName} has been saved.`); | ||
} | ||
} | ||
``` | ||
### Remove registered services or reset container state | ||
If you need to remove registered service from container simply use `Container.remove(...)` method. | ||
Also you can completely reset the container by calling `Container.reset()` method. | ||
This will effectively remove all registered services from the container. | ||
## Samples | ||
@@ -311,0 +478,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
55235
37.95%38
153.33%568
54.77%467
55.67%1
-50%22
15.79%1
Infinity%