I have a base class as follows where HttpClient and BusyService should be singletons global across the scope of the application:
export class BaseFetchService {
constructor(private readonly baseApi: string, private readonly httpClient: HttpClient, private readonly busyService: BusyService) { }
protected async _load<T extends IEntity>(id: string, action: string = "") {
const url = action && action.length > 0 ? `${this.baseApi}/${action}/${id}` : `${this.baseApi}/${id}`;
this.busyService.on();
const data = await (await this.httpClient.fetch(url)).json();
this.busyService.off();
return data as T;
}
etc...
}
I then inherit from the BaseFetchService
in client-service.ts
@autoinject
export class ClientService extends BaseFetchService {
constructor(private readonly clientService: ClientService, httpClient: HttpClient, busyService: BusyService) {
super("client", httpClient, busyService);
}
}
Is there some way to configure httpClient and busyService so that I can change the BaseFetchService
to obtain the singleton instance of these classes so that I do not have to inject them into the constructor?
Something like …
export class BaseFetchService {
private httpClient: HttpClient;
private busyService: BusyService;
constructor(private readonly baseApi: string){
this.httpClient = get_instance_of_HttpClient;
this.busyService = get_instance_of_BusyService;
}
}
allowing me now to inherit ClientService as
export class ClientService extends BaseFetchService {
constructor(private readonly clientService: ClientService) {
super("client");
}
}
Many thanks
you could register and get them manually from the aurelia Container. not sure if this is what you’re after.
---
name: "Dependency Injection: Basics"
description: Learn about how to leverage Aurelia's dependency injection container, the power behind all object creation in Aurelia applications.
author: Rob Eisenberg (http://robeisenberg.com)
---
## Introduction
When building applications, it's often necessary to take a "divide and conquer" approach by breaking down complex problems into a series of simpler problems. In an object-oriented world, this translates to breaking down complex objects into a series of smaller objects, each focusing on a single concern, and collaborating with the others to form a complex system and model its behavior.
A dependency injection container is a tool that can simplify the process of decomposing such a system. Often times, when developers go through the work of destructuring a system, they introduce a new complexity of "re-assembling" the smaller parts again at runtime. This is what a dependency injection container can do for you, using simple declarative hints.
## Injection
Let's say we have a `CustomerEditScreen` that needs to load a `Customer` entity by ID from a web service. We wouldn't want to place all the details of our AJAX implementation inside our `CustomerEditScreen` class. Instead, we would want to factor that into a `CustomerService` class that our `CustomerEditScreen`, or any other class, can use when it needs to load a `Customer`. Aurelia's dependency injection container lets you accomplish this by declaring that the `CustomerEditScreen` needs to have a `CustomerService` injected at creation time.
The mechanism for declaring a class's dependencies depends on the language you have chosen to author your application with.
Typically, you would use Decorators, an ES Next feature supported by both Babel and TypeScript. Here's what it looks like to declare that the `CustomerEditScreen` needs a `CustomerService`:
<code-listing heading="CustomerEditScreen Injection">
<source-code lang="ES 2015">
This file has been truncated. show original
Yes - I read that, but must confess that I didn’t understand it!
All the examples at the very bottom of the article are passing the singleton classes as parameters into the constructor , which is what I was hoping to avoid.
I was hoping that I could “new them up” in the body of the constructor.
bigopon
October 16, 2018, 12:43pm
4
You can assume that Container.instance
(the global / root Container
) is setup properly, and you can do in the constructor:
this.thatService = Container.instance.get(ThatServiceClass)
Though I’d argue against it, it’s quite against maintainability as you will lose track of dependency flow over time (i.e why would ThatServiceClass
be instantiated differently compared to the rest, in a framework obtrusive way).
Also, for me, as long reading the code doesn’t involve guessing & interpreting, the code is probably gonna last.
1 Like
That’s great - that’s exactly what I was looking for.
The reason I could justify it to myself, is that all of the services inherit from the one BaseFetchService
.
In the age of dependency injection I’m not sure it’s good practice to rely on user code instantiated from the Aurelia top level container since Global Variables/Functions can be so easily misused not by the original writer but others maintaining the code at a later date. If something goes wrong it can be difficult to track down something that can be accessed/changed from anywhere in the code.
You’re absolutely correct. After trying it for about 30 minutes, I scrapped the idea and went back to correctly implementing dependency injection.
All I was trying to do was save a miniscule amount of typing - hardly compensates for the amount of debugging I had to do!
1 Like