我最近开始使用tsyringe
,遇到了如何解决依赖关系的问题。一个可重复的场景解释如下:
class Client {
exec(svcNum: number) {
console.log("Executing ", svcNum);
}
}
@injectable()
class Service1 {
private readonly num = 1;
constructor(private client: Client) {}
serve() {
this.client.exec(this.num);
}
}
@injectable()
class Service2 {
private readonly num = 2;
constructor(private client: Client) {}
serve() {
this.client.exec(this.num);
}
}
我有一个Client
类,它是Service1
和Service2
使用的依赖项。这些问题可以像这样简单地解决:
const resolvedSvc1 = container.resolve(Service1);
const resolvedSvc2 = container.resolve(Service2);
现在我需要的是这样的东西:
container.register(Service1, { useClass: Service1 });
container.register(Service2, { useClass: Service2 });
const services = [ Service1, Service2 ]; // typeof Service1 | Service 2
services.forEach((svc) => {
//container.register((svc as any).name, { useClass: svc });
if (container.isRegistered((svc as any).name)) {
console.log("Found registered service ", svc.name);
}
const resolved = container.resolve<typeof svc>(svc.name);
(resolved as any).serve();
});
这不起作用,TypeScript在我运行代码时抱怨Error: Attempted to resolve unregistered dependency token: "Service1"
;此外,console.log
在if
块中不打印任何内容。我发现svc
有一个并集类型Service1 | Service2
,这可能是问题的原因。有什么方法可以在运行时以这种方式动态解析服务的依赖关系吗?将svc
缩小到适当的类型(即,我想Service1
或Service2
都可以(。
您正在使用class
注册服务,但随后尝试通过name
:检索它们
container.register(Service1, { useClass: Service1 });
// ^^^^^^^^ ✅ registering the class here
const resolved = container.resolve<typeof svc>(svc.name);
// ❌ trying to resolve by name ^^^^^^^^
有两种解决方案:
// Option 1: register by class and resolve by class
container.register(Service1, { useClass: Service1 });
// ^^^^^^^^ ✅ register by class
const resolved = container.resolve<typeof svc>(svc);
// ✅ resolve by class ^^^
// Option 2: register using the class name and resolve by class or class name
container.register(Service1.name, { useClass: Service1 });
// ^^^^^^^^^^^^^ ✅ register by class name
// can resolve by class
const resolved = container.resolve<typeof svc>(svc);
// ✅ resolve by class ^^^
// can resolve by class name
const resolved = container.resolve<typeof svc>(svc.name);
// ✅ resolve by class name ^^^^