Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Named Service doesn`t work #652

Closed
michaeldouglasdev opened this issue Feb 18, 2022 · 11 comments
Closed

fix: Named Service doesn`t work #652

michaeldouglasdev opened this issue Feb 18, 2022 · 11 comments
Labels
status: awaiting answer Awaiting answer from the author of issue or PR.

Comments

@michaeldouglasdev
Copy link

Description

Named Service doesn`t work, but works with Container.set.

TypeDI version: 0.10.0

I've tried using version 0.8.0, but it doesn't work either.

I don't want to inject via constructor with private, as I want to use the Stategy Design Pattern and that way it wouldn't work, at least as far as I know.

Error message:
Service with "ClassB" identifier was not found in the container. Register it before usage via explicitly calling the "Container.set" function or using the "@service()" decorator.

Minimal code-snippet showcasing the problem

@Service('ClassB')
export class ClassB {

  execute() {
    console.log('execute Class B')
  }
}

@Service('ClassA')
export class ClassA {

  execute() {
    const classB = Container.get("ClassB");
  }
}

Expected behavior

Expected to return a Class B instance

Actual behavior

Does not return a Class B instance.

Error message:
Service with "ClassB" identifier was not found in the container. Register it before usage via explicitly calling the "Container.set" function or using the "@service()" decorator.

@michaeldouglasdev michaeldouglasdev added status: needs triage Issues which needs to be reproduced to be verified report. type: fix Issues describing a broken feature. labels Feb 18, 2022
@matheusriios
Copy link

I have same problem. I mentioned here ISSUE

@attilaorosz
Copy link
Member

@michaeldouglasdev I think you have a little problem in your @Service decorator. The syntax is @Service({id: 'ClassB'}) not @Service('ClassB').

This snippet works as expected for me

@Service({id: 'ClassB'})
export class ClassB {

  execute() {
    console.log('execute Class B')
  }
}

@Service({id: 'ClassA'})
export class ClassA {

  execute() {
    const classB = Container.get<ClassB>("ClassB");
    classB.execute();
  }
}

const inst = Container.get<ClassA>('ClassA');
inst.execute();

@attilaorosz attilaorosz added status: awaiting answer Awaiting answer from the author of issue or PR. and removed type: fix Issues describing a broken feature. status: needs triage Issues which needs to be reproduced to be verified report. labels Mar 7, 2022
@attilaorosz
Copy link
Member

@michaeldouglasdev Sorry, I was on the develop branch... Tested it on master and I cannot reproduce it with this snippet

@Service('ClassB')
export class ClassB {

  execute() {
    console.log('execute Class B')
  }
}

@Service('ClassA')
export class ClassA {

  execute() {
    const classB = Container.get<ClassB>("ClassB");
    classB.execute();
  }
}

const inst = Container.get<ClassA>('ClassA');
inst.execute();

Could you provide a reproduction repo?

@jeesim2
Copy link

jeesim2 commented Mar 10, 2022

In my case, Named Service that in other files are failed to be discovered.

There are 6 Services. Relative to the test case file,

  • In Same file, Unnamed --> FOUND
  • In Sibling file, Unnamed --> FOUND
  • In Subdirectory file, Unnamed --> FOUND
  • In Same file, Named --> FOUND
  • In Sibling file, Named --> NOT FOUND
  • In Subdirectory file, Name --> NOT FOUND

Test cases and results

describe("Test", () => {
    it("TestSameFile", () => {
        assert.equal(Container.get(TestSameFile).run(), true)
    })
    it("TestSibling", () => {
        assert.equal(Container.get(TestSibling).run(), true)
    })
    it("TestSub", () => {
        assert.equal(Container.get(TestSub).run(), true)
    })
    it("TestSameFileNamed", () => {
        assert.equal(Container.get<any>('TestSameFileNamed').run(), true)
    })
    it("TestSiblingNamed", () => {
        assert.equal(Container.get<any>('TestSiblingNamed').run(), true)
    })
    it("TestSubNamed", () => {
        assert.equal(Container.get<any>('TestSubNamed').run(), true)
    })
})


@Service()
export class TestSameFile {
    public run(): boolean {
        return true;
    }
}

@Service('TestSameFileNamed')
export class TestSameFileNamed {
    public run(): boolean {
        return true;
    }
}

Only two were failed to discovered.

image

Which are Named and not in the same file.

directory structure

image

whole project

https://github.com/jeesim2/test-typedi/blob/main/app/test.spec.ts

test-typedi.zip

Is there anything that I missed?

@attilaorosz
Copy link
Member

attilaorosz commented Mar 10, 2022

@jeesim2 typedi does not run a full filesystem check for services. Your example fails because those named services are never imported thus the decorator never runs so it does not get registered. Can you try your example but instead of using any, you actually reference the classes?

@jeesim2
Copy link

jeesim2 commented Mar 10, 2022

@attilaorosz It also fails when I give type to the get()

    it("TestSiblingNamed", () => {
        assert.equal(Container.get<TestSiblingNamed>('TestSiblingNamed').run(), true)
    })
ServiceNotFoundError: Service with "TestSiblingNamed" identifier was not found in the container. Register it before usage via explicitly calling the "Container.set" function or using the "@Service()" decorator.
    at ContainerInstance.get (node_modules/src/container-instance.class.ts:75:11)
    at Function.get (node_modules/src/container.class.ts:61:32)
    at Context.it (app/test.spec.ts:22:32)
    at process.topLevelDomainCallback (domain.js:126:23)

Named service only can be discovered when it is defined at same file with caller.

BTW, My usecase is that,
With node cli application, user can input Service Name at the runtime.
And I want to run the service that named as given.
It is something like dynamic service execution. : )

@michaeldouglasdev
Copy link
Author

Hello, guys!

I solved it this way, it wasn't quite what I wanted, but that's how I'm doing it

@Service()
export class GetUserService {
  async execute(searchUser: SearchUserModel): Promise<UserModel> {
    const { type, value } = searchUser;

    // Take a good look at Container.get, specifically in getUserStrategyType
    const getUserStrategyService = Container.get<GetUserStrategyService>(getUserStrategyType[type]);
    const userModel = await getUserStrategyService.execute(value);

    return userModel;
  }
}
export const getUserStrategyType: { [key in SearchUserTypeModel]: ThisType<GetUserStrategyService> } = {
  [SearchUserTypeModel.CPF]: GetUserByCpfService,
  [SearchUserTypeModel.ID_WEB]: GetUserByIdWebService,
  [SearchUserTypeModel.LOGIN_TOKEN]: GetUserByLoginTokenService,
  [SearchUserTypeModel.EMAIL]: GetUserByEmailService,
};

export interface SearchUserModel {
  type: SearchUserTypeModel;
  value: string;
}

export enum SearchUserTypeModel {
  ID_WEB = 'ID_WEB',
  CPF = 'CPF',
  LOGIN_TOKEN = 'LOGIN_TOKEN',
  EMAIL = 'EMAIL',
}
export interface GetUserStrategyService {
  execute(value: string | number): Promise<UserModel>;
}

@sgentile
Copy link

@jeesim2 typedi does not run a full filesystem check for services. Your example fails because those named services are never imported thus the decorator never runs so it does not get registered. Can you try your example but instead of using any, you actually reference the classes?

Not sure I follow this statement - it should be looking for all items marked as @service ??? That is the point of the typedi registration process ?

@sgentile
Copy link

(btw, this is causing quite a few issues moving from 0.8.0 to 0.10.0)

@attilaorosz
Copy link
Member

Closing this in favor or #636

@github-actions
Copy link

github-actions bot commented May 4, 2022

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
status: awaiting answer Awaiting answer from the author of issue or PR.
Development

No branches or pull requests

5 participants