stho01
3/3/2017 - 10:39 AM

The activator class contains various methods for creating a instance of a class.

The activator class contains various methods for creating a instance of a class.

namespace Utils {
    "use strict";

    /**
     * The activator class contains various methods for creating 
     * a instance of a class. 
     */
    export class Activator {

        /**
         * Tries to create instance within the namespaces given.
         * If the class does not exists null is returned.
         * 
         * @param {string}      name                - The name of the class that shall be instantiated 
         * @param {string[]}    namespaces          - The namespaces to search within.
         * @param {[]}          [constructorArgs]   - The arguments that is passed in to the constructor upon creation.   
         * @returns {T}
         */
        public static tryCreateInstanceWithinNamespaces<T>(name: string, namespaces: string[], constructorArgs: any[] = []): T {
            if (name == null) { 
                throw new ReferenceError("argument name cannot be null"); 
            }

            let instance : T = null;
            constructorArgs.unshift(name);

            if(Activator.classExists(name)) {
                instance = <T>Activator.createInstance.apply(this, constructorArgs);
            } else {
                for (let i = 0; i < namespaces.length; i++) {
                    let fullName = namespaces[i] + "." + name;
                    constructorArgs[0] = fullName;
                    if(Activator.classExists(fullName)) {
                        instance = <T>Activator.createInstance.apply(this, constructorArgs);
                    }
                }
            }
            
            return instance;
        }

        /**
         * Creates an instance of class name with namespace.
         * 
         * @param {string}  name                - The name of the class that shall be instantiated
         * @param {...}     constructorArgs     - The arguments that is passed in to the constructor upon creation.
         * @returns {T}
         */
        public static createInstance<T>(name: string, ...constructorArgs: any[]): T {
            if (name == null) { throw new ReferenceError("argument name cannot be null"); }
            
            // Splits up the name e.g. Namespace.ClassName = [Namespace, ClassName]   
            let functionPath      : string[]        = name.split(".");
            
            // can either be a object or a function. 
            // The last result should be a function if not, the class does not exist.
            let currentStepOnPath : Object|Function = (window || this);
            
            for (let i = 0, len = functionPath.length; i < len; i++) {
                currentStepOnPath = currentStepOnPath[functionPath[i]];
            }

            if (typeof currentStepOnPath !== "function") {
                // The function was not found..
                throw new Error("No function or class with name [" + name + "] was found in the system");
            }
            
            return new (Function.prototype.bind.apply(currentStepOnPath, arguments));
        }
        
        /**
         * Checks if a class name is valid and exists.
         * 
         * @param {string}  name    - The name of the class that is about to be checked for existence. 
         */
        public static classExists(name: string) : boolean {
            if(name == null) { 
                return false; 
            }

            // Splits up the name e.g. Namespace.ClassName = [Namespace, ClassName]   
            let functionPath        : string[]              = name.split(".");
            
            // can either be a object or a function. 
            // The last result should be a function if not, the class does not exist.
            let currentStepOnPath   : Object|Function       = (window || this);
            
            // Loop through the function path and check if the 
            // current step exists in path.
            for (let i = 0, len = functionPath.length; i < len; i++) {
                if(currentStepOnPath === void 0) {
                    return false;
                }
                currentStepOnPath = currentStepOnPath[functionPath[i]];
            }

            return (typeof currentStepOnPath === "function");
        }
    }
}