You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: readme.md
+136-3
Original file line number
Diff line number
Diff line change
@@ -25,9 +25,11 @@ The name itself designed to make My Own IoC Container become your IoC Container,
25
25
26
26
Check installation part to make My Own IoC Container become Your Own IoC Container.
27
27
28
+
## Code Status
29
+
Stable, the library actually extracted from my internal project, and used in several small projects.
28
30
29
31
## Prerequisites
30
-
First prerequisites is you need to understand how My Own IoC Container work, refer to [How Its Work](how-its-work.md), believe me its easier than you thing.
32
+
First prerequisites is you need to understand how My Own IoC Container work, refer to [How Its Work](#how-its-work), believe me its easier than you think.
31
33
32
34
To use My Own IoC Container required you to use TypeScript with below `tsconfig.json`:
33
35
@@ -41,13 +43,17 @@ To use My Own IoC Container required you to use TypeScript with below `tsconfig.
41
43
}
42
44
```
43
45
46
+
* Transpile target: ES6 minimum
47
+
* Experimental decorators enabled
48
+
* Emit decorator metadata enabled
49
+
44
50
All above configuration is required.
45
51
46
52
# Features
47
53
My Own IoC Container support most of common IoC Container features:
48
54
49
55
-[x] Single file, copy - paste able, less then 15kb/300 lines of code
50
-
-[x]Supported Singleton and Transient lifestyle (Transient is default)
56
+
-[x]Lifestyle support: Singleton and Transient (Transient is default)
51
57
-[x] Constructor injection
52
58
-[x] Inject by type
53
59
-[x] Inject by name for interface injection
@@ -306,6 +312,7 @@ const container = new Container();
Above code showing that we intercept the execution of `Computer.start()` method adding console log before and after execution.
327
334
328
-
> Second parameter of the `onCreated` method is instance of `Kernel`
335
+
> Second parameter of the `onCreated` method is instance of `Kernel`
336
+
337
+
# How Its Work
338
+
339
+
Basically all IoC Container consist of two main big part: Registration part and Resolution part. Registration part convert registered type into component model, resolution part analyze the component model dependency graph and convert component model into type instance.
340
+
341
+
> NOTE
342
+
>
343
+
> below explanation and code snippet intended to be as simple as possible to easier for you to understand. In the real implementation of My Own IoC Container is a lot more robust and extensible than that but still easy to understand.
344
+
345
+
## Registration
346
+
347
+
For example we have classes below, and register it in the container.
348
+
349
+
```typescript
350
+
//classes
351
+
interfaceMonitor {}
352
+
classLGMonitorimplementsMonitor { }
353
+
classPowerSupply {}
354
+
classComputer {
355
+
constructor(
356
+
//inject by name (interface injection)
357
+
@inject.name("Monitor") privatemonitor:Monitor
358
+
//inject by type
359
+
privatepower:PowerSupply){ }
360
+
}
361
+
362
+
//registration
363
+
container.register("Monitor").asType(LGMonitor)
364
+
container.register(PowerSupply)
365
+
container.register(Computer)
366
+
```
367
+
368
+
Registration part will convert above class into a Component Models like below
369
+
370
+
```typescript
371
+
[{
372
+
kind: "Type",
373
+
name: "Monitor"
374
+
type: LGMonitor,
375
+
lifeStyle: "Transient",
376
+
dependencies: []
377
+
}, {
378
+
kind: "Type",
379
+
//the name is auto generated, because registered by type
380
+
//name will be used as a key on singleton cache
381
+
name: "auto:PowerSupply"
382
+
type: PowerSupply,
383
+
lifeStyle: "Transient",
384
+
dependencies: []
385
+
}, {
386
+
kind: "Type",
387
+
name: "auto:Computer"
388
+
type: Computer,
389
+
lifeStyle: "Transient",
390
+
//list of constructor parameters,
391
+
//for more advanced scenario can be list of properties for property injection
392
+
//note that dependencies only contain the Name or Type of the
393
+
//dependent type, further we use recursion to resolve them
394
+
dependencies: ["Monitor", PowerSupply]
395
+
}]
396
+
```
397
+
398
+
`kind` of component model used to differentiate how the component will be instantiated. Some IoC container have several registration kind: Register by type, register by instance, register for auto factory etc etc. Each registration kind has different resolving logic.
399
+
400
+
## Resolution
401
+
Resolution part consist of two part: dependency graph analysis and resolution. Dependency graph analysis needed to catch issues that hard to trace like:
402
+
* A type dependent to another type that is not registered in the container
403
+
* A type contains circular dependency
404
+
* A type registration causing [captive dependency](http://blog.ploeh.dk/2014/06/02/captive-dependency/)
405
+
406
+
I will not explain the dependency graph analysis part because its not important part, you can check the [Topological Sort](https://en.wikipedia.org/wiki/Topological_sorting) for basic understanding of the analysis.
407
+
408
+
We continue to resolution part, when your code asks for resolution like below:
409
+
410
+
```typescript
411
+
const computer =container.resolve(Computer)
412
+
```
413
+
414
+
The resolution part perform operation like below
415
+
416
+
```typescript
417
+
//array of component model comes from registration
Above code will create instance of the requested type and resolve the parameter recursively. For example if we request the `Computer` class, the component model is like be below:
449
+
450
+
```typescript
451
+
{
452
+
kind: "Type",
453
+
name: "auto:Computer"
454
+
type: Computer,
455
+
lifeStyle: "Transient",
456
+
dependencies: ["Monitor", PowerSupply]
457
+
}
458
+
```
459
+
460
+
So the instantiation process `new model.type()` is the same as `new Computer()`. then we recursively resolve the `model.dependencies` that is `"Monitor"` and `PowerSupply` then assigned them as the parameter of the `Computer` object using spread `...` operator.
0 commit comments