Skip to content

Instantly share code, notes, and snippets.

@msyfls123
Created April 27, 2022 10:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msyfls123/2879f46b8537077e0e9cf3502e71a6d7 to your computer and use it in GitHub Desktop.
Save msyfls123/2879f46b8537077e0e9cf3502e71a6d7 to your computer and use it in GitHub Desktop.
dependency injection
import 'reflect-metadata';
abstract class Singleton {
static getInstance: () => Singleton;
}
const INJECTION_KEY = 'inject:';
const inject =
(kls: typeof Singleton): PropertyDecorator =>
(target, propertyKey: string) => {
Reflect.defineMetadata(`${INJECTION_KEY}${propertyKey}`, kls, target);
};
function injectable(target) {
return new Proxy(target, {
construct(cls: Function, args, receiver) {
const obj = Reflect.construct(cls, args, receiver);
Reflect.getMetadataKeys(obj)
.filter((v) => v.startsWith(INJECTION_KEY))
.forEach((key) => {
const propertyKey = key.substring(INJECTION_KEY.length);
const kls = Reflect.getMetadata(key, obj);
Reflect.defineProperty(obj, propertyKey, {
get: () => kls.getInstance(),
});
});
return obj;
},
});
}
class Example {
static instance: Example;
static getInstance() {
if (!this.instance) {
this.instance = new this();
}
return this.instance;
}
prop = 42;
}
@injectable
class Application {
@inject(Example)
private example: Example;
public callMe() {
console.log(this.example.prop);
}
}
const app = new Application();
app.callMe();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment