inversify / InversifyJS

A powerful and lightweight inversion of control container for JavaScript & Node.js apps powered by TypeScript.
http://inversify.io/
MIT License
11.33k stars 719 forks source link

Binding inside a factory method #1414

Open 1b0x opened 2 years ago

1b0x commented 2 years ago

Hello there, I have a question about this piece of code:

This is how my factory looks like. As you can see I'm binding/unbinding some classes inside this factory method.

export function SceneFactory(context: interfaces.Context) {
    return (key: string, scene: any) => {
        // Unbind the scene if it exists
        if (context.container.isBound(key)) {
            context.container.unbind(key);
        }

        // Bind the new scene class
        context.container.bind<IScene>(key).to(scene);
        return context.container.get<IScene>(key);
    };
}

I'm using it like that:

@injectable()
export class SceneManager implements ISceneManager {
    scenes: IScene[];

    constructor(
        @inject(ISceneFactory)
        protected sceneFactory: (key: string, scene: any) => IScene
    ) { }

    add(key: string, scene: IScene) {
        const sceneInstance = this.sceneFactory(key, scene);

        this.scenes.push(sceneInstance);
    }
}

class SceneA extends Scene {}
class SceneB extends Scene {}
sceneManager.add('sceneA', SceneA);
sceneManager.add('sceneB', SceneB);

So, the question is: Is it okay to bind/unbind classes in a factory method? Is it a good approach to do that?

kyle-johnson commented 2 years ago

A better approach is to create a child container in the factory. This way, the original container isn't modified:

export function SceneFactory(context: interfaces.Context) {
    return (key: string, scene: any) => {
        const childContainer = context.container.createChild();

        // Bind the new scene class (since this is bound in the child container, it will override any existing binds)
        childContainer.bind<IScene>(key).to(scene);
        return childContainer.get<IScene>(key);
    };
}

More info here: https://github.com/inversify/InversifyJS/blob/master/wiki/hierarchical_di.md

1b0x commented 2 years ago

Thank you! I really appreciate it!

Is it good to create multiple child containers for other manager classes? Let's say that If I have Sound Manager (which has SoundFactory), should I create a new child container?