UNPKG

@e22m4u/js-service

Version:

Реализация принципа инверсии управления для JavaScript

140 lines (128 loc) 3.72 kB
import {isServiceContainer} from './utils/index.js'; import {InvalidArgumentError} from '@e22m4u/js-format'; import {ServiceContainer} from './service-container.js'; /** * Service class name. * * @type {string} */ export const SERVICE_CLASS_NAME = 'Service'; /** * Service. */ export class Service { /** * Kinds. * * @type {string[]} */ static kinds = [SERVICE_CLASS_NAME]; /** * Container. * * @protected * @type {ServiceContainer} */ _container; /** * Container. * * @type {ServiceContainer} */ get container() { return this._container; } /** * Constructor. * * @param {ServiceContainer} [container] */ constructor(container = undefined) { if (isServiceContainer(container)) { this._container = container; } else if (container !== undefined) { throw new InvalidArgumentError( 'Parameter "container" must be an instance ' + 'of ServiceContainer, but %v was given.', container, ); } else { this._container = new ServiceContainer(); // если класс данного экземпляра наследуется от базового, // то при создании внутреннего контейнера, текущий экземпляр // будет зарегистрирован внутри своего же контейнера if (this.constructor !== Service) { // проблемой дублирования пакетов (когда npm устанавливает // несколько версий одной библиотеки в разные папки node_modules) // можно пренебречь, так как в данном конкретном случае ссылка // на класс Service замкнута внутри лексической области одного // файла и проверяется относительно самой себя, а не пришедшего // извне объекта this._container.set(this.constructor, this); } } } /** * Получить существующий или новый экземпляр. * * @param {*} ctor * @param {*} args * @returns {*} */ getService(ctor, ...args) { return this._container.get(ctor, ...args); } /** * Получить существующий или новый экземпляр, * только если конструктор зарегистрирован. * * @param {*} ctor * @param {*} args * @returns {*} */ getRegisteredService(ctor, ...args) { return this._container.getRegistered(ctor, ...args); } /** * Проверка существования конструктора в контейнере. * * @param {*} ctor * @returns {boolean} */ hasService(ctor) { return this._container.has(ctor); } /** * Добавить конструктор в контейнер. * * @param {*} ctor * @param {*} args * @returns {this} */ addService(ctor, ...args) { this._container.add(ctor, ...args); return this; } /** * Добавить конструктор и создать экземпляр. * * @param {*} ctor * @param {*} args * @returns {this} */ useService(ctor, ...args) { this._container.use(ctor, ...args); return this; } /** * Добавить конструктор и связанный экземпляр. * * @param {*} ctor * @param {*} service * @returns {this} */ setService(ctor, service) { this._container.set(ctor, service); return this; } }