我正在努力在未由 NestJS 实例化的类中实现依赖注入。 我想在我的 NestJS 项目中使用 Colyseus 框架 (https://colyseus.io/),并且我需要注入服务,例如用于验证客户端。
export class GameRoom extends Room<GameRoomState> {
constructor (
private authService: AuthService
) { super() }
onCreate(options: any) {
this.setState(new GameRoomState())
}
async onAuth(client: Client, options: any, request: IncomingMessage) {
if (request.headers.cookies) {
const sessionId = this.authService.getSessionId(request.headers.cookie)
const user = await this.authService.authSessionId(sessionId)
if (!user) {
throw new ServerError(401, 'Invalid Session ID')
}
return true
} else {
throw new ServerError(401,'You need to provide a "session" cookie with a valid Session ID')
}
}
}
然后,如果我们将房间类传递给服务器的定义函数,它将实例化它
this.server.define("GameRoom", GameRoom)
(https://docs.colyseus.io/server/api/#define-roomname-string-room-room-options-any)
问题是,尽管有一个提供 AuthService 和 GameRoom 类的模块,但当服务器触发“onAuth”回调时,this.authService 将是未定义的,因为 Colyseus 服务器使用的 GameRoom 不是由 Nest 实例化的
Colyseus框架不提供通过传递房间实例来定义房间的方法,仅提供房间类型。 有什么方法可以为我的 GameRoom 类提供服务吗?我没有看到任何方法可以做到这一点,因为 Nest 没有实例化它...... 非常感谢任何愿意提供帮助的人:)
我尝试修改 Colyseus 包来实现一个采用 Room 实例而不是类型的构造函数,但我是一个新手开发人员,但没有成功。 我尝试了很多东西,包括基于属性的注入、使用 NestJS 的 moduleRef,但最终没有任何效果,因为 Colyseus 服务器不使用与我的模块相同的房间实例
我解决这个问题的方法是创建一个从 Room 类获取参数类型的函数,然后从这些类型中,可以通过 NextApplication 实例检索依赖项。
这是我写的函数
function injectDeps<T extends { new (...args: any[]): Room }>(
app: INestApplication,
target: T,
): T {
const selfDeps = Reflect.getMetadata('self:paramtypes', target) || [];
const dependencies = Reflect.getMetadata('design:paramtypes', target) || [];
selfDeps.forEach((dep: any) => {
dependencies[dep.index] = dep.param;
});
const injectables =
dependencies.map((dependency: any) => {
return app.get(dependency);
}) || [];
return class extends target {
constructor(...args: any[]) {
super(...injectables);
}
};
}
在这个函数中,我使用了metadatakey
design:paramtypes
来获取Room类构造函数中所有参数的类型。
self:paramtypes
用于检索使用@Inject()
装饰器注入的参数类型。
然后你可以如下定义,
server.define('test', injectDeps(app, BaseRoom));
注意,你的房间等级必须用
@Injectable()
装饰器标记。
这是示例代码。