InversifyJS icon indicating copy to clipboard operation
InversifyJS copied to clipboard

Scope not working with net.Socket

Open fabiohvp opened this issue 4 years ago • 0 comments

I have an NodeJS application that is using net.Socket and I need to some instances be scoped from inside socket.on("data") event.

Expected Behavior

Container should resolve to children objects the same instance that I got in the parent object.

//InjectionContainer.ts
import { Container } from "inversify";

export const container = new Container({
	autoBindInjectable: true,
	defaultScope: "Transient",
	skipBaseClassChecks: true,
});

//InversifyConfig.ts
import { container } from "./InjectionContainer";

export enum InjectionToken {
	IClientPacketFactory = "Factory<IClientPacket>",
	IConnection = "IConnection",
	IServer = "IServer",
}

export function bindAll() {
	container.bind("ClientPacket_1").to(Packet_0x01).inRequestScope(); //I have a list of this with different number
	container
		.bind<IConnection>(InjectionToken.IConnection)
		.to(Connection).inRequestScope();

	container
		.bind<IClientPacket>(InjectionToken.IClientPacketFactory)
		.toFactory(
			(context: interfaces.Context) =>
				(cmd: string, buffer: Buffer) => {
					const packet = context.container.get<IClientPacket>(
						`ClientPacket_${cmd}`
					);
					packet.init(buffer);
					return packet;
				}
	);
}

//Server.ts
@injectable()
import { bindAll, InjectionToken } "./InjectionConfiguration";
import { container } from './InjectionContainer';

export class Server {
        constructor() {
                bindAll();
                const serverSocket = net.createServer((clientSocket: net.Socket) => {
        	        clientSocket.on("data", async (buffer: Buffer) => {
                                const connection = container.get<IConnection>(InjectionToken.IConnection);
                                connection.id = 1;
                                await connection .receive(buffer);
        	        });
                });
        }
}

//Connection.ts
import { inject, injectable } from "inversify";
import { InjectionToken } "./InjectionConfiguration";

export interface IConnection  {
	receive(buffer: Buffer): Promise<void>;
}

@injectable()
export class Connection implements IConnection {
	@inject(InjectionToken.IClientPacketFactory)
	private _clientPacketFactory: (
		cmd: string,
		buffer: Buffer
	) => IClientPacket;

	id: string;

	async receive(buffer: Buffer) {
		const cmd = buffer[0].toString();
		const packet = this._clientPacketFactory(cmd, buffer);
		await packet.handle();
	}
}

//Packet_0x01.ts
import { inject, injectable } from "inversify";
import { InjectionToken } "./InjectionConfiguration";

@injectable()
export class Packet_0x1 extends ClientPacket {
	@inject(InjectionToken.IConnection) //tried receiving by constructor too, didn't work either
	private _connection: IConnection;

	async handle(): Promise<void> {
             console.log(this._connection.id == 1); //**should be true**
	}
}

Context

I am developing a client/server game emulator and I want to use dependency injection to avoid having to pass parameters inside my classes and to facilitate the creation of unit tests. I still can't make my repository public but if needed I can create a repo with the above code (that is just a small part from the project)

Your Environment

inversify ^5.1.1 reflect-metadata ^0.1.13 windows 10 pro node v14.17.1

fabiohvp avatar Jul 14 '21 06:07 fabiohvp