question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Feature request: top-down dependency injection

See original GitHub issue

The @Service decorator is only called if the implementation of the service is explicitly called. If this typename is known to the constructor, it kind of defeats the point of DI as the controller now has a dependency at least on the name and path of the dependency.

It would be helpful to have a top-down DI initialization where the token is set at fastify initialization.

example use case:

//IBlogService.ts
import { BlogPost } from './models/BlogPost';

export interface IBlogService
{
    async getBlogPosts(): Promise<Array<BlogPost>>;
}
//SqliteBlogService.ts
import { IBlogService } from './services/IBlogService';
import { BlogPost } from '../models/BlogPost';

export class SqliteBlogService implements IBlogService {
    async getBlogPosts(): Promise<Array<BlogPost>>{ /* ... */ };
}
//BlogController.ts

//SqliteBlogService @Service is never called because it's never explicitly imported anywhere
import { IBlogService } from '../services/IBlogService';

@Controller({
    route: '/api/blogposts'
})
export class BlogController {
    constructor(private blogService: IBlogService) { }

    @GET()
    public async getBlogPosts(req, res): Promise<Array<BlogPosts>> {
        return this.blogService.getBlogPosts();
    }
}

Top down injection could be something like:

//app.ts
import { injectables } from 'fastify-decorators';
import { IBlogService } from './services/IBlogService';

//injection goes before constructor discovery
if(environment === 'development') {
    injectables.injectSingleton<IBlogService>(new SqliteBlogService());
} else if(environment === 'production') {
    injectables.injectSingleton<IBlogService>(new MySQLBlogService());
}

fastify.register(bootstrap, {
    /* ... */
})

this would allow services to be defined as interfaces so that you’re not dependent on any particular implementation within the controllers, which is the point of DI

The workaround is to simply import whatever implementations you want in app.ts so that the @Service decorator is called before the @Inject decorators in the controller, but this is obviously code smell

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
L2jLigacommented, Nov 21, 2022

Published as v3.15.0

1reaction
L2jLigacommented, Nov 1, 2022

The workaround is to simply import whatever implementations you want in app.ts so that the @service decorator is called before the @Inject decorators in the controller, but this is obviously code smell

It’s purely depends on you bootstrap style, in case when you use autoload option and import service directly within you index.ts, then import of service is executed before controllers and their dependencies are loaded, but it can not work in case when you specify controllers to be loaded and it can depends on imports order. Long story short: it depends who was required/imported first, but yeah, can agree, this is code smell

Read more comments on GitHub >

github_iconTop Results From Across the Web

Layered Architecture, Dependency Injection, and Dependency ...
In this section of code I am coupling the presenter to SqlConnection, SqlCommand, and SqlDataReader objects. In reality, worse than the coupling ...
Read more >
Feature request: dependency injection everywhere · Issue #166
I'd like to use dependency injection in pipes, filters and global guards as well. Usecase: business validation with AOP, separated to the ...
Read more >
Effective Dependency Injection in Apex - Salesforce Developers
A common issue when programming is how to keep your code properly organized — both to aid in readability, decrease the amount of...
Read more >
How I Translate Feature Requests into Code - Michael-F-Bryan
This lets you determine when the feature request has been fulfilled, and gives you a way to ward off scope creep.
Read more >
C# Dependency Injection with Autofac - YouTube
Dependency Injection in C# can be a really confusing topic. Yet, when done right, Dependency Injection can be one of the best things...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found