I have a class whose constructor has two arguments; one is a dependency, the other is a configuration property:
@inject(Dependency)
class MyClass{
constructor(dependency, config){
}
}
How can I make use of Aurelia's dependency injection to automatically inject the dependency but allow the class's consumer to specify the config value?
I have a class whose constructor has two arguments; one is a dependency, the other is a configuration property:
@inject(Dependency)
class MyClass{
constructor(dependency, config){
}
}
How can I make use of Aurelia's dependency injection to automatically inject the dependency but allow the class's consumer to specify the config value?
Share Improve this question edited Jan 14, 2016 at 17:31 Jeremy Danyow 26.4k12 gold badges90 silver badges135 bronze badges asked Jan 14, 2016 at 15:45 Gorse horseGorse horse 5,5831 gold badge22 silver badges15 bronze badges2 Answers
Reset to default 19Here are some options:
Option 0: Factory Resolver
foo.js
import {inject} from 'aurelia-framework';
import {FooDependency} from './foo-dependency';
@inject(FooDependency)
export class Foo {
constructor(dep, config) {
}
}
needs-foo.js
import {inject, Factory} from 'aurelia-framework';
import {Foo} from './foo';
@inject(Factory.of(Foo))
export class NeedsFoo {
constructor(fooFactory) {
let config = {};
this.foo = fooFactory(config);
}
}
Option 1: Factory
foo.js
import {inject} from 'aurelia-framework';
import {FooDependency} from './foo-dependency';
class Foo {
constructor(dep, config) {
}
}
@inject(FooDependency)
export class FooFactory {
constructor(dep) {
this.dep = dep;
}
makeFoo(config) {
return new Foo(this.dep, config);
}
}
needs-foo.js
import {inject} from 'aurelia-framework';
import {FooFactory} from './foo';
@inject(FooFactory)
export class NeedsFoo {
constructor(fooFactory) {
let config = {};
this.foo = fooFactory.makeFoo(config);
}
}
Option 2: Child Container
foo.js
import {inject} from 'aurelia-framework';
import {FooDependency} from './foo-dependency';
export const configKey = 'config';
@inject(FooDependency, configKey)
export class Foo {
constructor(dep, config) {
}
}
needs-foo.js
import {inject, Container} from 'aurelia-framework';
import {Foo, configKey} from './foo';
@inject(Container)
export class NeedsFoo {
constructor(container) {
let config = {};
let childContainer = container.createChild();
childContainer.registerInstance(configKey, config);
this.foo = childContainer.get(Foo);
}
}
Option 3: Brute Force
foo.js
export class Foo {
constructor(dep, config) {
}
}
needs-foo.js
import {inject, Container} from 'aurelia-framework';
import {FooDependency} from './foo-dependency';
import {Foo} from './foo';
@inject(Container)
export class NeedsFoo {
constructor(container) {
let config = {};
let dep = container.get(FooDependency);
this.foo = new Foo(dep, config);
}
}
In the end I created a custom resolver, which means the code is nice and modular and easy to use in other classes.
foo.js
import {inject} from 'aurelia-framework';
import {FooDependency} from './foo-dependency';
@inject(Dependency)
export class Foo{
constructor(dep, cfg){}
static useArgs(...args){
return new Resolver(Foo, args);
}
}
@resolver
class Resolver{
constructor(Class, args){
this.Class = Class;
this.args = args;
}
get(container){
var Class = this.Class,
// Class.inject is the array of the class's dependencies
// we need to resolve them all before they're useful
dependencies = Class.inject.map((dep)=>container.get(dep)),
// Pass the resolved dependencies + any additional arguments to the new class
args = dependencies.concat(this.args);
return new Class(...args);
}
}
needs-foo.js
import {inject} from 'aurelia-framework';
import {Foo} from 'foo';
@inject(Foo.useArgs('my config'))
export class NeedsFoo{
constructor(fooConfigured){
}
}