用动态类名实例化对象的简单方法



当要实例化的类名在变量中时,有没有一种简单的方法来实例化对象?我正在将一个现有的应用程序移植到TS/Node.js,我有一个带有类工厂的抽象基类,我在其中传递我想要的类类型作为参数,它本身来自环境。

目前,我想让代码尽可能接近原始代码,但我看不到一种简单的方法可以做到这一点,不需要我每次添加继承自基类的新子类时都修改基类。

我想要的代码的简化版本基本上看起来是这样的:

export abstract class Foo {
static async get(className : string) : FOO {
if (!FOO._instance) {
FOO._instance = new className();
}
return FOO._instance;
}
}
... then ...
export class Bar extends Foo {
/* stuff */
}
... and finally used as ...
const baz = await Foo.get('Bar');
// baz is now an instance of Bar.

实际的代码比这更复杂,但除了包含new className()的行之外,所有代码都能工作,我找不到将要实例化的类名传递给new的方法,也找不到其他实例化类的方法。PHP、Java、Perl和C#都做得很简单,但我似乎在TS中找不到类似工作的方法。我最接近的方法是,例如,在工厂getter中的一个switch语句,它知道所有的子类,这是可行的,但并不完全是最优的。

TIA。

您可以让子类在抽象基类中注册自己,抽象基类将类名映射到实际类:

export abstract class Foo {
static _classMapping: { [key: string]: { new(): Foo }} = {}
static _instance : Foo | null = null

static get(className : string) : Foo | null {
if (!Foo._instance) {
Foo._instance = new (this._classMapping[className])();
}
return Foo._instance;
}
static _register(className : string, classRef : { new(): Foo }) {
Foo._classMapping[className] = classRef;
}
}
// ... then ...
export class Bar extends Foo {
/* stuff */
}
Foo._register('Bar', Bar)
// ... and finally used as ...
const baz = await Foo.get('Bar');
console.log(baz.constructor.name)
// baz is now an instance of Bar.

最新更新