Link Search Menu Expand Document

Injector and Provider

Injector

Injector is the core object of tarpit; it records Token and Provider pairs and searches Provider by given Token.

Injector created with no parent called root injector, it has a fake parent as NullInjector.

NullInjector is an object with methods get and has which’s function signature is as same as Injector except always finds nothing.

You can get the Injector from the Injection Point:

@TpService()
class SomeService {
    constructor(
        private injector: Injector
    ) {
    }
    
    check_another() {
        return this.injector.has(AnotherService)
    }
}

Methods of Injector

Injector has a write method set, and two read method get and has.

The method set will record Token-Provider pair to the injector itself. The methods get and has both search self first, and then the parent, and the parent of the parent, until the NullInjector.

Searching Process

E.g.

const root_injector = Injector.create()
const child_injector = Injector.create(root_injector)


// Assume that FirstProvider is a ClassProvider of FirstService
root_injector.set(FirstService, FirstProvider) 
// Assume that SecondProvider is a ClassProvider of SecondService
child_injector.set(SecondService, SecondProvider) 

child_injector.has(SecondService) 
// true  ===> check child itself, exist -> return true

child_injector.has(FirstService) 
// true  ===> check child itself, not exist -> check parent(root_injector), exist -> return true

root_injector.has(FirstService) 
// true  ===> check root itself, exist -> return true

root_injector.has(SecondService) 
// false  ===> check root itself, not exist -> check parent(NullInjector) -> return false

Event Bus

Another responsibility of the Injector is to act as an event bus.

E.g.

@TpService()
class SomeService {
    constructor(
        private injector: Injector
    ) {
        this.injector.on('start', () => this.setup())
    }

    setup() {
        // do something to setup
    }
}

Provider

A Provider is the wrapper of the instance creation process. All kinds of Providers have the method create(). Tarpit will call this method to get the value that needs to be passed.

There three kind of Providers.

ClassProvider

ClassProvider is a Provider for a class(the object with new() signature). Tarpit will resolve dependencies of the class, and create instance for them.

ClassProvider uses a singleton pattern, which is to say that a ClassProvider will create the instance only once; it will return the same instance on every call of the method create(). If you want to control more details, try FactoryProvider.

Here are the properties of the ClassProvider definition.

Property Description
provide Injection Token to search Provider.
useClass Create instance with this class.
root If this Provider should add to the root injector.

You can define a ClassProvider as below

@TpModule({
    providers: [
        { provide: FirstService, useClass: ModifiedFirstService, root: true },
        { provide: FirstService, useClass: FirstService, root: true },
        { provide: FirstService, useClass: FirstService },
        FirstService // short for above
    ]
})
class SomeModule {
}

FactoryProvider

FactoryProvider is a Provider that wraps a function of the creation process. You can define the creation process by the delivered function.

Every time resolve the result of a FactoryProvider, the delivered function will be called.

Here are the properties of the FactoryProvider definition.

Property Description
provide Injection Token to search Provider.
useFactory Create result by this function.
deps Dependencies of the function.
root If this Provider should add to the root injector.

You can define a FactoryProvider as below

const pre_created = new FirstService()

@TpModule({
    providers: [
        { provide: FirstService, useFactory: (a: AnotherService) => new FirstService(), deps: [ AnotherService ] },
        { provide: FirstService, useFactory: () => new FirstService() },
        { provide: FirstService, useFactory: () => pre_created },
    ]
})
class SomeModule {
}

ValueProvider

ValueProvider is a Provider that wraps the constant. It is usually for some configuration or state management.

Here are the properties of the FactoryProvider definition.

Property Description
provide Injection Token to search Provider.
useValue Constant to store, Provider.create() will return this value.
root If this Provider should add to the root injector.
multi If record multi value for this Token.

If multi set to true, Provider.create() will return an array instead of single value.

You can define a ValueProvider as below

@TpModule({
    providers: [
        { provide: Symbol.for('cc.tarpit.custom'), useValue: 3, root: true}, 
        { provide: Symbol.for('cc.tarpit.some_string'), useValue: 'sentence', multi: true }, 
    ]
})
class SomeModule {
}