Last active
June 24, 2016 21:38
-
-
Save matjaz/62e5e6b7073ee09b56016eaadaefa3de to your computer and use it in GitHub Desktop.
aurelia-property-injection - based on https://github.com/matjaz/aurelia-property-injection & https://github.com/heruan/aurelia-property-injection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {autoinject, inject} from './decorators' | |
class Greeter { | |
welcome(name): string { | |
return `Welcome ${name}!`; | |
} | |
} | |
@autoinject // used for constructor DI | |
export class App { | |
@autoinject greeter: Greeter; // magic | |
@inject(Greeter) // used for non-typed languages | |
greeter2: Greeter; | |
constructor (private g: Greeter) { | |
console.log(this.g) | |
console.log(this.g === this.greeter) // true | |
console.log(this.g === this.greeter2) // true | |
// return this | |
// constructor returns new object: | |
// return { | |
// greeatAll() { | |
// console.log(this.greeter.welcome('my master')) | |
// } | |
// } | |
} | |
greetAll() { | |
this.message = this.greeter.welcome('everybody'); | |
} | |
message: string = 'Welcome!'; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {metadata} from 'aurelia-metadata'; | |
import {PropertyInjectorInvoker} from './invoker'; | |
import {inject} from 'aurelia-property-injection-heruan'; // heruan implementation | |
export function autoinject (potentialTarget?: any, potentialKey?: any): any { | |
const deco = function (target, key, descriptor?) { | |
if (!key) { | |
target.inject = metadata.getOwn(metadata.paramTypes, target, key) || Object.freeze([]); | |
} else if (!descriptor) { | |
let targetConstructor = target.constructor; | |
if (!targetConstructor.injectProperties) { | |
targetConstructor.injectProperties = Object.create(null); | |
// set invoker for constructor function | |
metadata.define(metadata.invoker, PropertyInjectorInvoker.instance, targetConstructor); | |
} | |
targetConstructor.injectProperties[key] = metadata.getOwn('design:type', target, key); | |
} | |
}; | |
return potentialTarget ? deco(potentialTarget, potentialKey) : deco; | |
} | |
export {inject} from 'aurelia-property-injection-heruan'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {Invoker} from 'aurelia-dependency-injection'; | |
let singleton; | |
export class PropertyInjectorInvoker implements Invoker { | |
static get instance () { | |
return singleton || (singleton = new PropertyInjectorInvoker); | |
} | |
} | |
PropertyInjectorInvoker.prototype.invoke = invoke; | |
PropertyInjectorInvoker.prototype.invokeWithDynamicDependencies = invoke; | |
function invoke (container, fn, staticDependencies, dynamicDependencies) { | |
var injectProps; | |
const injectProperties = fn.injectProperties; | |
if (injectProperties) { | |
injectProps = Object.create(null); | |
for (let property in injectProperties) { | |
injectProps[property] = { | |
value: container.get(injectProperties[property]) | |
}; | |
} | |
} | |
// inject properties as soon as object is created, before calling constructor | |
let instance = Object.create(fn.prototype || null, injectProps); | |
let i = staticDependencies.length; | |
let args = new Array(i); | |
while (i--) { | |
args[i] = container.get(staticDependencies[i]); | |
} | |
if (dynamicDependencies) { | |
args = args.concat(dynamicDependencies); | |
} | |
var ctReturn = fn.apply(instance, args); | |
if (ctReturn && ctReturn !== instance && typeof ctReturn === 'object') { | |
// if constructor returns object inject properties to new object | |
instance = ctReturn; | |
if (injectProperties) { | |
for (let property in injectProperties) { | |
Object.defineProperty(instance, property, { | |
value: container.get(injectProperties[property]) | |
}); | |
} | |
} | |
} | |
return instance; | |
} |
Not really. Object.create
creates new object with prototype of fn
and then we apply fn as constructor function. (same as new
)
In JavaScript constructor can return different object, hence the second injectProps()
(not used/commented out in this gist). But it looks this doesn't work well with Aurelia.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If I understand correctly, you first inject in the properties of an instance created by
Object.create()
, then produce another instance with the real constructor and then inject again in the properties of that instance. Is that right?