thiagobustamante / typescript-ioc

A Lightweight annotation-based dependency injection container for typescript.
MIT License
526 stars 64 forks source link

How to use singleton scope #60

Closed robertnisipeanu closed 4 years ago

robertnisipeanu commented 4 years ago

So I tried following the getting started from NPM however, i stumbled across this problem: when using new ClassName() when that class has the @Singleton decorator, it still calls the constructor of that class every time I call new ClassName(), it'll only call once if I use Container.get(ClassName).

Example:

@Singleton
class Test{

    constructor() {
        new Test1(10);
        new Test1();
        new Test1();
    }
}

@Singleton
class Test1 {
    constructor() {
        console.log("Test1");
    }
}

Will print the following:

Test1
Test1
Test1

While this:

@Singleton
class Test{

    constructor() {
        Container.get(Test1);
        Container.get(Test1);
        Container.get(Test1);
    }
}

@Singleton
class Test1 {
    a: number;

    constructor(a?: number) {
        if(a) this.a = a;
        console.log("Test1");
    }
}

Would print this:

Test1

Why is that the case with the first example?

Kampfmoehre commented 4 years ago

When you call the constructor directly, you circumvent the IOC framework. Take a look at the Readme section which explains how to prevent direct constructor calls for Singletons.

I think the better code for your use case would be to inject the Singleton dependency:

@Singleton
class Test{
    @Inject private test: Test1;
    constructor() {
      // you can now access this.test
    }
}

@Singleton
@OnlyInstantiableByContainer // This makes new Test1() throw a Type Error
class Test1 {
    a: number;

    constructor(a?: number) {
        if(a) this.a = a;
        console.log("Test1");
    }
}

This way the IOC framework automatically handles your dependency and will provide you always the same instance of the Test1 class.