Skip to content

Commit 5871dd1

Browse files
committed
wip
1 parent 0950c04 commit 5871dd1

4 files changed

Lines changed: 75 additions & 10 deletions

File tree

package-lock.json

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"@babel/types": "^7.22.5",
3333
"reflect-metadata": "^0.1.13",
3434
"tcp-port-used": "^1.0.2",
35-
"tslib": "^2.6.2"
35+
"tslib": "^2.8.1"
3636
},
3737
"devDependencies": {
3838
"@types/mssql": "^8.1.2",

src/di/di.ts

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,29 @@ const serviceProvider = Symbol("serviceProvider");
1818

1919
const globalServiceProvider = Symbol("globalInstance");
2020

21+
let newServiceTarget = null;
22+
23+
const patched = Symbol("serviceConstructorPatched");
24+
25+
const patchClass = (type) => {
26+
if (type[patched]) {
27+
return;
28+
}
29+
const parent = Object.getPrototypeOf(type);
30+
if (parent === null || parent === Object || parent === Object.prototype) {
31+
// eslint-disable-next-line @typescript-eslint/ban-types
32+
const old = type.constructor as Function;
33+
type.constructor = function (...a) {
34+
this[serviceProvider] = newServiceTarget;
35+
return old.apply(this, a);
36+
};
37+
type[patched] = true;
38+
return;
39+
}
40+
patchClass(parent);
41+
type[patched] = true;
42+
};
43+
2144
export class ServiceProvider implements IDisposable {
2245

2346
public static from(owner: any) {
@@ -167,10 +190,14 @@ export class ServiceProvider implements IDisposable {
167190
}
168191

169192
private createFromType(type, key = type): any {
193+
const old = newServiceTarget;
194+
newServiceTarget = this;
170195
const injectTypes = type[injectServiceTypesSymbol] as any[];
171196
const injectServices = injectTypes
172197
? injectTypes.map((x) => this.resolve(x))
173198
: [];
199+
patchClass(type.prototype);
200+
type = type.prototype?.constructor ?? type;
174201
const instance = new type(... injectServices);
175202
this.map.set(key, instance);
176203
instance[serviceProvider] = this;
@@ -180,6 +207,7 @@ export class ServiceProvider implements IDisposable {
180207
}
181208
// initialize properties...
182209
this.resolveProperties(instance, type);
210+
newServiceTarget = old;
183211
return instance;
184212
}
185213

@@ -264,9 +292,9 @@ export default function Inject(target, key, index?: number): any {
264292

265293
const pType = (Reflect as any).getMetadata("design:type", target, key);
266294
(target[injectServiceKeysSymbol] ??= {})[key] = pType;
267-
Object.defineProperty(target, key, {
295+
const descriptor = {
268296
get() {
269-
const result = ServiceProvider.resolve(this, pType);
297+
const result = ServiceProvider.resolve(newServiceTarget ?? this, pType);
270298
// get is compatible with AtomWatcher
271299
// as it will ignore getter and it will
272300
// not try to set a binding refresher
@@ -276,9 +304,9 @@ export default function Inject(target, key, index?: number): any {
276304
return result;
277305
},
278306
configurable: true
279-
});
280-
281-
307+
};
308+
Object.defineProperty(target, key, descriptor);
309+
return descriptor;
282310
}
283311

284312
export function Register(kind: ServiceKind, factory?: (sp: ServiceProvider) => any) {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import Inject, { RegisterSingleton, ServiceProvider } from "../../di/di.js";
2+
3+
const services = new ServiceProvider();
4+
5+
@RegisterSingleton
6+
class Root {
7+
8+
public root = "root";
9+
}
10+
11+
@RegisterSingleton
12+
class Branch {
13+
14+
@Inject branchRoot: Root;
15+
16+
public branch = "branch";
17+
}
18+
19+
@RegisterSingleton
20+
class Leaf {
21+
@Inject branch: Branch;
22+
23+
leaf: string;
24+
25+
constructor() {
26+
this.leaf = this.branch.branchRoot.root + " -> " +this.branch.branch + " -> leaf";
27+
}
28+
}
29+
30+
export default function() {
31+
const leaf = services.resolve(Leaf);
32+
console.log(leaf.leaf);
33+
}
34+
35+
36+

0 commit comments

Comments
 (0)