通过名称动态实例化对象

时间:2019-10-15 11:36:17

标签: javascript node.js typescript

我必须解析非结构化日志文件。这些日志文件具有多个不同的消息。每个消息都有特定的结构。例如:

TIMESTAMP:MESSAGE_NAME1:PARAM1:PARAM2:PARAM3
TIMESTAMP:MESSAGE_NAME2:PARAM1:PARAM2:PARAM3:PARAM4:PARAM5

如您所见,这些消息是结构化的,但是可以具有不同的参数和不同数量的参数。我有90多种不同的消息,其中某些消息甚至具有可以多次出现的参数,因此它们将是数组。

我想要实现的是为每条消息都提供一个类。为此,我已经可以提取消息名称。但是,我不知道如何在不使用非常宽松的switch语句的情况下根据消息名称实例化对象,这对我而言似乎是糟糕的编码。

例如,我想做的是这样的事情:

getInstanceByClassName(className: string, params: any[]) {
    //magic code
    return instance;
}

我试图通过执行此答案中所示的操作来创建类似的功能: https://stackoverflow.com/a/15339429/11411437

但是,我遇到错误,如果没有new关键字就无法实例化。 我正在使用Typescript。

编辑:

我拥有的是这样的课程:

export class Message1 {
    param1: string;
    param2: string;
    param3: string;
    param4: string;
    param5: string;
    param6: string;
}

我解析日志并获取消息名称,例如:

let name: string = splitArray[0];

现在,我想实例化当前我想要的类:

if (name === "Message1") {
    let message: Message1 = new Message1(splitArray[1], splitArray[2], ...);
} else if (name === "Message2") ...

(或带开关盒。.

很明显,这将导致大量的if陈述或转换案例。

还有另一种方法吗?特别是考虑到每个构造函数可以具有不同数量的参数。

如果您需要更多信息,请告诉我,以便我提供。

1 个答案:

答案 0 :(得分:1)

在我看来,可以使用单个类

class Message {
   public messageName: string;
   public time: string;
   public params: string[];
   constructor(logMessage: string) {
       const parts = logMessage.split(":");
       // TODO: Make it a date
       this.time = parts.shift();
       this.messageName = parts.shift();
       this.params = parts;
   }
}

如果您实际上有单独的Message1/2/3/4类,则情况不同,因此您将需要在字符串和构造函数之间建立一些映射,以便能够正确地实例化它们。

由于您需要进入泛型以保持类型安全,因此我们需要查看这些类的外观,并且从示例代码来看,这些类看起来几乎都是复制粘贴的