I didn't find a good example how to deal with the issue, when in inheritance, some constructor parameters should be defined and passed by subclass(es), and rest should be injected.
export class Superclass {
static inject = [Service1, Service2];
constructor(
//parameter(s) intented to be passed by subclasses
parameterFromSubclass,
//services intented to be injected
service1, service2) {
this.service1 = service1;
this.service2 = service2;
//do stuff based on parameterFromSubclass
}
}
To make it more complex, subclasses might also need to inject their own services.
export class Subclass extends Superclass {
static inject = [Service3];
constructor(service3) {
const param = 'parameter from subclass'; //could be anything
super(param, ...?);
this.service3 = service3;
}
}
One obvious solution would be to list+inject all dependencies on the subclass. But this would require that all subclasses has to maintain also the dependencies of the superclass.
export class Subclass extends Superclass {
static inject = [Service1, Service2, Service3];
constructor(service1, service2, service3) {
const param = 'parameter from subclass';
super(param, service1, service2);
this.service3 = service3;
}
}
Luckily, Aurelia DI supports inheritance when defining injects (be that either as a static array or class decorator), so that base class dependencies are also "inherited", so does not need to be specified explicitly and can be passed using spread operator. This way, subclass gets all the dependencies injected.
export class Subclass extends Superclass {
static inject = [Service1];
constructor(service1, ...rest) {
const param = 'parameter from subclass';
super(param, ...rest);
this.service3 = service3;
}
}
One other alternative would be using Factory, but that cannot be applied to inheritance and would mean having to refactor base class into a service. So when using inheritance, I found the solution above simpler.
Remark: the question and the wording is pretty much leading to the answer, sorry about that.
One other alternative would be to not use constructor injection or decorator based injection in your base class and just use Aurelia's container instance manually there, avoiding the inheritance issue altogether
Possible, although have some disadvantages: * static access of Container.instance would give the root container, which might not respect lifetime setups. Services injected to base class might also have dependencies * generally, constructor parameters are much cleaner and does not mix unnecessary DI-logic into a class * manual access increases complexity, for each parameter, one has to add container.get(Foo)