Typescript: Dependency Injection / Port Resolver

Date: 2018-05-17
export interface IPortResolver {
    resolve<T>(name : string) : T;
}
import { IPortResolver } from '../ports/IPortResolver';

class BaseResolver implements IPortResolver {
    resolve<T>(name: string): T { return this.resolver.resolve(name); }
    protected resolver: IPortResolver;
    public setPortResolver(portResolver: IPortResolver) {
        this.resolver = portResolver;
    }
}
class AppDomain extends BaseResolver {
    get IRequestUserSession() { return this.resolve<IRequestUserSession>("IRequestUserSession"); }
    get IRequestRefreshSession() { return this.resolve<IRequestRefreshSession>("IRequestRefreshSession"); }
    get IRequestClearUserSession() { return this.resolve<IRequestClearUserSession>("IRequestClearUserSession"); }
    get IHandleExceptions() { return this.resolve<IHandleExceptions>("IHandleExceptions"); }
    get INavigator() { return this.resolve<INavigator>("INavigator"); }
    get IEventHandler() { return this.resolve<IEventHandler>("IEventHandler"); }
    get IEventEmitter() { return this.resolve<IEventEmitter>("IEventEmitter"); }    
}

export const appDomain = new AppDomain();
import { IPortResolver } from '../ports/IPortResolver';

export class PortResolver implements IPortResolver {
    private _container : any = {};
    constructor() {

    }
    register<T>(name, fn : () => T) {
        this._container[name] = fn;
    }
    registerInstance<T>(name, fn : () => T) {
        let _instance = null;
        let getInstance = (fn) => {
            return () => {
                if (!_instance) {
                    _instance = fn();
                }
                return _instance;
            };
        };
        this._container[name] = getInstance(fn);
    }
    resolve<T>(name : string) : T {
        if (name in this._container && typeof this._container[name] == 'function') {
            return this._container[name]() as T;
        }
        throw new Error('PortResolver can not resolve '+ name);
    }
}
import { PortResolver } from "../adapters/PortResolver";
import { appDomain } from "../domain/AppDomain";
import { Injectable, NgModule, ComponentFactoryResolver } from "@angular/core";
import { AngularHttpClientPlug } from "../adapters/AngularAdapter/AngularHttpClientPlug";
import { HttpClient } from "@angular/common/http";
import { SweetAlertPlug } from "../adapters/PresentationAdapter/SweetAlertPlug";
import { AngularRoutingPlug } from "../adapters/AngularAdapter/AngularRoutingPlug";
import { Router } from "@angular/router";
import { NgBlockUI, BlockUI } from "ng-block-ui";
import { TokenManagerPlug } from "../adapters/TokenManagerAdapter/TokenManagerPlug";
import { ClipboardPlug } from "../adapters/DomAdapter/ClipboardPlug";
import { IHttpClient } from '../ports/IHttpClient';
import { ICanNavigate } from '../ports/ICanNavigate';
import { ICanManageToken } from '../ports/ICanManageToken';
import { ICanCopyToClipboard } from '../ports/ICanCopyToClipboard';
import { ICanCheckPermissions } from '../ports/ICanCheckPermissions';
import { PermissionsPlug } from '../adapters/PermissionsAdapter/PermissionsPlug';
import { ICanDoHttpRequests } from '../ports/ICanDoHttpRequests';
import { HttpRequestPlug } from '../adapters/HttpRequestAdapter/HttpRequestPlug';
import { ICanGiveUserTypes } from '../ports/ICanGiveUserTypes';
import { UserTypePlug } from '../adapters/WebApiAdapter/UserTypePlug';
import { NotifierPlug } from '../adapters/PresentationAdapter/NotifierPlug';
import { ICanNotify } from '../ports/ICanNotify';
import { ICanGiveApiInfo } from '../ports/ICanGiveApiInfo';
import { ApiInfoPlug } from '../adapters/WebApiAdapter/ApiInfoPlug';
import { ICanShowAlert } from '../ports/ICanShowAlert';
import { ICanShowDialog } from '../ports/IDialogAdapter';
import { DialogPlug } from '../adapters/PresentationAdapter/DialogPlug';
import { ICanTranslate } from '../ports/ICanTranslate';
import { TranslationPlug } from '../adapters/TranslationAdapter/TranslationPlug';
import { ICanCRUDStorage } from '../ports/ICanCRUDStorage';
import { LocalStoragePlug } from '../adapters/LocalStorageAdapter/LocalStoragePlug';
import { ICanCRUDTransformation } from '../ports/ICanCRUDTransformation';
import { TransformationPlug } from '../adapters/WebApiAdapter/TransformationPlug';
import { ICanCRUDUser } from '../ports/ICanCRUDUser';
import { UserPlug } from '../adapters/WebApiAdapter/UserPlug';
import { ICanGetCurrentUser } from '../ports/ICanGetCurrentUser';
import { CurrentUserPlug } from '../adapters/WebApiAdapter/CurrentUserPlug';
import { ICanBlockUI } from '../ports/ICanBlockUI';
import { NgBlockUiPlug } from '../adapters/PresentationAdapter/NgBlockUiPlug';
import { ICanTransceiveEvents } from '../ports/ICanTransceiveEvents';
import { EventPlug } from '../adapters/EventAdapter/EventPlug';
import { ICanChangePasswords } from '../ports/ICanChangePasswords';
import { ChangePasswordPlug } from '../adapters/WebApiAdapter/ChangePasswordPlug';
import { ICanGeneratePassword } from '../ports/ICanGeneratePassword';
import { GeneratePasswordPlug } from '../adapters/WebApiAdapter/GeneratePasswordPlug';


@Injectable()
export class Wiring {
    @BlockUI() blockUI: NgBlockUI;

        getBaseUrl() {
        let baseUrl = "http://localhost:9125";
        if ((window as any).config) {
            baseUrl = (window as any).config.WebApiUrl || "http://localhost:9125";
        }
        return baseUrl;
    }

    constructor(httpClient: HttpClient, componentFactoryResolver: ComponentFactoryResolver, router: Router) {

        let blockUI = this.blockUI;

        const portResolver = new PortResolver();

        portResolver.registerInstance<IHttpClient>('IHttpClient', () => new AngularHttpClientPlug(httpClient));
        portResolver.registerInstance<ICanNavigate>('ICanNavigate', () => new AngularRoutingPlug(router));
        portResolver.registerInstance<ICanManageToken>('ICanManageToken', () => new TokenManagerPlug(this.getBaseUrl() + "/token"));
        portResolver.registerInstance<ICanCopyToClipboard>('ICanCopyToClipboard', () => new ClipboardPlug());

        portResolver.registerInstance<ICanCheckPermissions>('ICanCheckPermissions', () => new PermissionsPlug());
        portResolver.register<ICanDoHttpRequests>('ICanDoHttpRequests', () => new HttpRequestPlug(this.getBaseUrl()));
        portResolver.register<ICanGiveUserTypes>('ICanGiveUserTypes', () => new UserTypePlug());
        portResolver.register<ICanNotify>('ICanNotify', () => new NotifierPlug());
        portResolver.register<ICanGiveApiInfo>('ICanGiveApiInfo', () => new ApiInfoPlug());
        portResolver.register<ICanShowAlert>('ICanShowAlert', () => new SweetAlertPlug());
        portResolver.register<ICanShowDialog>('ICanShowDialog', () => new DialogPlug(componentFactoryResolver));
        portResolver.registerInstance<ICanTranslate>('ICanTranslate', () => new TranslationPlug());
        portResolver.register<ICanCRUDStorage>('ICanCRUDStorage', () => new LocalStoragePlug());
        portResolver.register<ICanCRUDUser>('ICanCRUDUser', () => new UserPlug());
        portResolver.register<ICanCRUDTransformation>('ICanCRUDTransformation', () => new TransformationPlug());
        portResolver.registerInstance<ICanGetCurrentUser>('ICanGetCurrentUser', () => new CurrentUserPlug());
        portResolver.register<ICanBlockUI>('ICanBlockUI', () => new NgBlockUiPlug(blockUI));
        portResolver.register<ICanTransceiveEvents>('ICanTransceiveEvents', () => new EventPlug());
        portResolver.registerInstance<ICanChangePasswords>('ICanChangePasswords', () => new ChangePasswordPlug());
        portResolver.register<ICanGeneratePassword>('ICanGeneratePassword', () => new GeneratePasswordPlug());

        appDomain.setPortResolver(portResolver);
    }
}
11000cookie-checkTypescript: Dependency Injection / Port Resolver