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: 2024_12_09_dependency-injection.md
+14-19Lines changed: 14 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ title: Relative simple and small type-driven dependency injection
6
6
7
7
Find time to modernize dependency injection in some services. The previous version involved simply passing the context object with fields for services.
8
8
9
-
```
9
+
```Scala
10
10
traitAppContext {
11
11
defservice1():Service1
12
12
defservice2():Service2
@@ -36,14 +36,13 @@ We will use approaches very close to what sideEffffECt describe in https://www.r
36
36
37
37
We will think that component `C` is provided if we can find AppProvicer[C]]
38
38
39
-
```
39
+
```Scala
40
40
traitAppContextProvider[T] {
41
41
defget:T
42
42
}
43
43
44
-
```
44
+
...
45
45
46
-
```
47
46
objectAppContext {
48
47
49
48
@@ -55,15 +54,14 @@ def apply[T](using AppContextProvider[T]): T =
55
54
}
56
55
```
57
56
58
-
59
57
If we have an implicit instance of the object, we think it's provided:
@@ -127,7 +122,7 @@ class UserSubscription(using AppContextProviders[(EmailService,UserDatabase)]) {
127
122
128
123
How to do this: at first, we will need a type-level machinery, which will select a first supertype of `T` from the tuple `Xs`:
129
124
130
-
```
125
+
```Scala
131
126
objectTupleIndex {
132
127
133
128
@@ -215,7 +210,7 @@ But this will still be boilerplate: We must enumerate dependencies twice and wri
215
210
216
211
To minimize this kind of boilerplate, we can introduce a convention for AppContextProviderModule, which defines its dependencies in type and automatic generation of instance providers:
217
212
218
-
```
213
+
```Scala
219
214
traitAppContextProviderModule[T] {
220
215
221
216
@@ -264,7 +259,7 @@ Yet one facility usually needed from the dependency injection framework is cachi
264
259
265
260
Let’s add cache type to the AppContext:
266
261
267
-
```
262
+
```Scala
268
263
objectAppContext {
269
264
270
265
@@ -292,7 +287,7 @@ object AppContext {
292
287
293
288
And let's deploy a simple convention: if the service requires `AppContext.Cache` as a dependency, then we consider this service cached. I.e., with manual setup of AppContextProvider this should look like this:
294
289
295
-
```
290
+
```Scala
296
291
objectFuelUsage {
297
292
298
293
given (usingAppContextProviders[(AppContext.Cache, Wheel, Rotor, Tail)]):AppContextProvider[FuelUsage] with
@@ -312,7 +307,7 @@ class appContextCacheClass[T] extends scala.annotation.StaticAnnotation
312
307
Cache operations will follow that annotation when calculating cacheKey[T].
313
308
Typical usage:
314
309
315
-
```
310
+
```Scala
316
311
traitUserSubscription
317
312
318
313
@appContextCacheClass[UserSubscription]
@@ -358,7 +353,7 @@ We can write a macro that should be called from the context inside a component d
358
353
359
354
I.e., a typical component definition will look like this:
0 commit comments