首页 > 解决方案 > 按名称动态实例化对象

问题描述

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

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关键字的情况下实例化。我正在使用打字稿。

编辑:

我所拥有的是这样的课程:

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 语句或 switch case。

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

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

标签: javascriptnode.jstypescript

解决方案


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

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的类,那是另一种情况,因此您需要在字符串和构造函数之间进行一些映射才能正确实例化它们。

我们需要看看这些类是什么样子,因为您需要进入泛型以保持类型安全,并且从您的示例代码中,这些类看起来几乎是复制粘贴的


推荐阅读