Tuesday, May 10, 2016

TypeScript - Reflection ie create object from its class name in string

Reflection

Reflection is a mechanism to talk to the metadata of classes or other programming constructs in programming language and do things without coding it. For example to listing out all the methods of a class where the class name is in string, invoking a method name by accepting the method name from user. Also creating an object without new keyword etc... Refer what says wiki on reflection for more details.

Creating object by its name not using new

In this post, we are going to see how we can create an object by knowing its name in a string variable. Since the value/name of class can be changed runtime, we cannot use new keyword. If we want we can use a switch construct based on the value in the string and have new in the case blocks. But that will work only when all the possible class names are known in advance. In a plugin model where anyone can add implemented classes at a later point, this switch mechanism will not work.

This is the class, whose object we are going to create.
module Company.App.Module {
    export class Greeter {
        constructor() {
        }
        greet(message: string) {
            return "Hello, " + message;
        }
    }
}
Below is the con
import Greeter = Company.App.Module.Greeter;
var obj: any = ObjectFactory.create("Company.App.Module.Greeter");
var greeter: Greeter = <Greeter>obj;
alert(greeter.greet("Joy"));
Look at the argument to ObjectFactory.create(). Its a string. So the question is how do we write the create() function.

Forbidden,dangerous JavaScript method eval()

For some reason, there are some constructs in programming language which are taught to be dangerous and should not use. eval() is one among that. But in this scenario, we are going to use eval() to do our job easier.
class ObjectFactory {
    static create(className: string) {
        var obj;
        eval("obj=new " + className + "()");
        return obj;
    }
}
To be frank eval() is not a feature of TypeScript. Its there in JavaScript for long and TypeScript cannot take the credit for reflection. Since its demonstrated in TypeScript, the title of this post contains TypeScript.

Security warning

If the className is accepted from user, there are chances for attack. If they enter a string like below and we use that string as is to call this method, it will just execute malicious code.

String(); (function malicionsFunction(){//malicious code})();new String

No comments: