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

Documentation about IOC Container #81

Open
paulosandinof opened this issue Oct 12, 2021 · 3 comments
Open

Documentation about IOC Container #81

paulosandinof opened this issue Oct 12, 2021 · 3 comments
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@paulosandinof
Copy link

Hi. I was trying the other day to use the new version of the framework to achieve something like Spring Boot does in Java with with it's IOC Container, and I noticed that website lacks a little more information about this. I wanted to write something like:

export default interface FooRepositoryInterface {
  findAll(): Promise<Foo>
}
export default class FooRepository implements FooRepositoryInterface{
  findAll(): Promise<Foo> {
    // Implementation
  }
}
export default interface FooServiceInterface {
  list(): Promise<Foo>
}
export default class FooService implements FooServiceInterface {

  constructor(public FooRepositoryInterface repository) {}

  list(): Promise<Foo> {
    return repository.findAll()
  }
}
export default class FooController {

  constructor(public FooServiceInterface service) {}

  index() {
    service.list()
  }
}

It is possible to achieve this kind of behavior with the current version of the framework? If it is, could you guys provide me some examples or guides in how to register the dependencies on the IOC container correctly? I tried to register the classes on the provider but I could achieve the result I wanted.
Thanks in advance.

@RomainLanz RomainLanz added the documentation Improvements or additions to documentation label Oct 13, 2021
@RomainLanz RomainLanz self-assigned this Oct 13, 2021
@RomainLanz
Copy link
Member

RomainLanz commented Oct 13, 2021

Hey @paulosandinof! 👋🏻

It is possible, but not directly like you are doing.
You can inject something using the @inject decorator.

import { inject } from '@adonisjs/core/build/standalone'
import YourServiceClass from 'App/Services/YourServiceClass'

@inject()
export default class UsersController {
  constructor(public myService: YourServiceClass) {}

  public async store({ request, auth }: HttpContextContract) {
    console.log(this.myService.name)
  }
}

I am planning to start writing the documentation about IoC soon.

@paulosandinof
Copy link
Author

Hi @RomainLanz, I was able to kind of reproduce what I wanted with the help of your comment. I'm going to put it here in order to help someone who had this same problem while the documentation gets updated.

Repository Interface

export default interface CityRepository {
    findAll(): string
}

Repository Implementation

export default class CityRepositoryImpl implements CityRepository {
    public findAll() {
        return 'find all'
    }
}

Service Interface

export default interface DashboardService {
    populateDashboard(): Promise<DashboardDTO>
    calculatePricing(): Promise<PricingDTO>
}

Service Implementation

@inject(['Repositories/CityRepository'])
export default class DashboardServiceImpl implements DashboardService {
    constructor(public cityRepository: CityRepository) {}

    public async populateDashboard() {
        return cityRepository.findAll()
    }
}

Controller Class

@inject(['Services/DashboardService'])
export default class DashboardController {
    constructor(public dashboardService: DashboardService) {}

    public async index() {
        return this.dashboardService.populateDashboard()
    }
}

I had to register the dependencies in the AppProvider class, particularly to be able to use dependency injection in classes that already depend of other classes.

export default class AppProvider {
  constructor(protected app: ApplicationContract) {}

  public register() {
    // Register your own bindings
    this.app.container.bind('Repositories/CityRepository', () => new CityRepositoryImpl())
    this.app.container.bind('Repositories/PlanRepository', () => new PlanRepositoryImpl())

    const cityRepository: CityRepository = this.app.container.use('Repositories/CityRepository')
    const planRepository: PlanRepository = this.app.container.use('Repositories/PlanRepository')

    this.app.container.singleton(
      'Services/DashboardService',
      () => new DashboardServiceImpl(cityRepository, planRepository)
    )
  }

  public async boot() {
    // IoC container is ready
  }

  public async ready() {
    // App is ready
  }

  public async shutdown() {
    // Cleanup, since app is going down
  }
}

Thanks for the help. I hope this helps someone else.

@qrhfz
Copy link

qrhfz commented Jul 19, 2022

Can i use documentation from legacy page (4.1)? Or the api is really different?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants