将修饰器应用于第三方类



我有一个DI容器类,它要求解析类以使用@Injectable()装饰器进行装饰,以便装饰类发出元数据并进行进一步的配置(非常像Angular DI工作,https://angular.io/guide/dependency-injection(。

为了将第三方类注册到我的容器中,我需要将@Injectable装饰器应用于我无法修改的类。想想像安装在node_modules中的记录器库这样的东西,我希望在我的容器中拥有它。

有没有办法将装饰器应用于第三方类?我在想这样的事情:

import {Container, Injectable} from "./Container";
import {Logger} from "@vendor/logger";
const container = new Container();
container.register(Logger, { useClass: Logger }); // not possible, since Logger is not decorated
container.register(decorate(Logger, Injectable), { useClass: Logger }); // something like this, which would allow for decorating a class with a certain decorator

我现在能想到的唯一解决方案是创建一个从真正的记录器类扩展的装饰代理类。但是代理所有第三方类似乎开销很大。

还有其他想法吗?

编辑以提供更多信息:

@Injectable装饰器是必需的,因为非修饰类不会发出元数据(这将使容器无法读取和解析其依赖项(。它只是通过向具有__INJECTABLE键和值true的修饰类添加一个元数据键来实现的 - 每当在容器中注册新服务时,它都会检查是否设置了__INJECTABLE标志,否则会引发错误。

下面是代理类的示例:

import {Container, Injectable} from "./Container";
import {Logger as ParentLogger} from "@vendor/logger";
// Proxy
@Injectable()
class Logger extends ParentLogger {
}
const container = new Container();
container.register(Logger, { useClass: Logger });

我想这应该有效,但需要为几乎每个第三方类创建代理。

您的decorate函数可能如下所示:

function Injectable() { return (_: any) => {} }
class ParentLogger { }
// Proxy
@Injectable()
class Logger extends ParentLogger {
}
function decorate<T extends { new(...args: any[]): any }>(sourceClass: T): T{
@Injectable()
class destinationClass extends sourceClass
{
constructor(...args: any[]) {
super(...args);
}
}
return destinationClass;
}
const DecoratedLogger = decorate(ParentLogger);

游乐场在这里。

如果其他人遇到这种情况,请在此处添加此内容。我在使用其他第三方基类的第三方应用程序时遇到了问题,最终调用了它。

decorate(injectable(), Object.getPrototypeOf(Events.EventEmitter));

我还发现这个标志之后将禁用此检查,因此您甚至不需要使第三方库中的基类可注入。它仍然可以工作,没有他们被注射

const container = new Container({ skipBaseClassChecks: true });

最新更新