|
1 | 1 | # Service Container (IoC Container)
|
2 | 2 |
|
3 | 3 |
|
| 4 | +- [Introduction](#introduction) |
| 5 | +- [Resolving Dependencies](#resolving-dependencies) |
| 6 | +- [When to Use The Container](#when-to-use-the-container) |
| 7 | +- [Binding](#binding) |
| 8 | + - [Singleton Bindings](#singleton-bindings) |
| 9 | +- [Resolving](#resolving) |
| 10 | + |
| 11 | + |
| 12 | + |
4 | 13 | ## Introduction
|
5 | 14 | Supercharge uses a service container to manage dependencies. The container allows you to register dependencies and retrieve them when needed. This setup supports dependency injection in your application. Well, dependency injection is a funky term that basically describes “injecting” dependencies into a class (or function).
|
6 | 15 |
|
@@ -34,19 +43,81 @@ class RedisCache implements CacheContract {
|
34 | 43 | The `RedisCache` should be responsible for the caching of items. A Redis client should store and retrieve individual cache items. The Redis cache itself shouldn’t worry about setting up a Redis client instance and connecting it to the Redis database. Here’s where the container comes handy: injecting a Redis client into the cache class .
|
35 | 44 |
|
36 | 45 |
|
37 |
| -## Resolving Dependendies |
| 46 | +## Resolving Dependencies |
38 | 47 | The Supercharge service container **does not** resolve dependencies automatically for you. You need to actively retrieve services from the container when needed.
|
39 | 48 |
|
40 | 49 | For example, you may need to retrieve a `Redis` service in your [service provider](/docs/service-providers) when building a custom Redis cache class.
|
41 | 50 |
|
42 | 51 |
|
43 | 52 | ## When to Use The Container
|
44 |
| -You should use the container when writing a Supercharge package that you're sharing with other Supercharge developers. Typically, you’re providing a service provider that binds your services into the container. |
| 53 | +You should use the container when writing a Supercharge package that you're sharing with other Supercharge developers. Typically you’re providing a service provider that binds your services into the container. |
45 | 54 |
|
46 | 55 |
|
47 | 56 | ## Binding
|
48 |
| -tba. |
| 57 | +Typically you’re registering your container bindings in [service providers](/docs/service-providers). Within service providers you’ve access to the application instance via the `this.app()` method. |
| 58 | + |
| 59 | +You can register a bindung using the `this.app().bind(identifier, closure)` method. The `bind` method expects a string or class constructor as an identifier and a closure returning the resolved class instance. When using a class constructor for the container binding, the service container automatically retrieves and uses the class name for that binding: |
| 60 | + |
| 61 | +```ts |
| 62 | +import { Application } from '@supercharge/contracts' |
| 63 | +import { DocsRenderer } from './services/docs-renderer' |
| 64 | +import { MarkdownRenderer } from './services/markdown-renderer' |
| 65 | + |
| 66 | +this.app().bind(MarkdownRenderer, (app: Application) => { |
| 67 | + const docsRenderer = this.app().make(DocsRenderer) |
| 68 | + |
| 69 | + return new MarkdownRenderer(docsRenderer) |
| 70 | +}) |
| 71 | +``` |
| 72 | + |
| 73 | +Supercharge will always create a new instance of the `MarkdownRenderer` when resolving it from the container. |
| 74 | + |
| 75 | +**Notice:** you can use the `app` instance to resolve already registered services from the container and use them in other services. Also, you’re receiving the `app` instance as an argument to your closure function. |
| 76 | + |
| 77 | +You may also use a string value as an identifier for container bindings: |
| 78 | + |
| 79 | +```ts |
| 80 | +import { Application } from '@supercharge/contracts' |
| 81 | +import { DocsRenderer } from './services/docs-renderer' |
| 82 | +import { MarkdownRenderer } from './services/markdown-renderer' |
| 83 | + |
| 84 | +this.app().bind('markdown.renderer', (app: Application) => { |
| 85 | + // … |
| 86 | +}) |
| 87 | + |
| 88 | +// then resolve it like this: |
| 89 | +const renderer = this.app().make('markdown.renderer') |
| 90 | +``` |
| 91 | + |
| 92 | + |
| 93 | +### Singleton Bindings |
| 94 | +The container supports a `singleton` method binding a class into the container that resolves once. A singleton binding will be cached and the same instance will be returned on subsequent calls into the container: |
| 95 | + |
| 96 | +```ts |
| 97 | +import { Application } from '@supercharge/contracts' |
| 98 | +import { DocsRenderer } from './services/docs-renderer' |
| 99 | +import { MarkdownRenderer } from './services/markdown-renderer' |
| 100 | + |
| 101 | +this.app().singleton(MarkdownRenderer, (app: Application) => { |
| 102 | + const docsRenderer = this.app().make(DocsRenderer) |
| 103 | + |
| 104 | + return new MarkdownRenderer(docsRenderer) |
| 105 | +}) |
| 106 | +``` |
49 | 107 |
|
50 | 108 |
|
51 | 109 | ## Resolving
|
52 |
| -tba. |
| 110 | +You can resolve class instances from the container using the `make` method. The `make` method accepts a string or class you wish to resolve: |
| 111 | + |
| 112 | +```ts |
| 113 | +import { MarkdownRenderer } from './services/markdown-renderer' |
| 114 | + |
| 115 | +const renderer = this.app().make(MarkdownRenderer) |
| 116 | +``` |
| 117 | + |
| 118 | +If you registered a service into the container using a string identifier, you can resolve it using the same key: |
| 119 | + |
| 120 | +```ts |
| 121 | +const renderer = this.app().make('markdown.renderer') |
| 122 | +``` |
| 123 | + |
0 commit comments