or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

context-dependent-wiring.mdcontext-free-wiring.mddynamic-instance-access.mdfactory-based-wiring.mdindex.md

context-free-wiring.mddocs/

0

# Context-Free Wiring

1

2

Context-free wiring with `autowire` creates instances using explicitly provided dependencies, without relying on the surrounding context. This approach is only available in Scala 3 and provides maximum flexibility in dependency specification.

3

4

## Core Functions

5

6

### autowire

7

8

Creates an instance of type `T` using provided dependencies. Missing dependencies are automatically created using public constructors or companion object `apply` methods.

9

10

```scala { .api }

11

inline def autowire[T](inline dependencies: Any*): T

12

```

13

14

**Parameters:**

15

- `dependencies: Any*` - Variable number of dependency specifications

16

17

**Returns:** Instance of type `T` with all dependencies wired

18

19

**Dependency Types:**

20

Each dependency parameter can be:

21

- **Instance**: Direct instance to use for injection

22

- **Function**: Function that creates an instance when called

23

- **Class**: `classOf[SomeType]` to instantiate the class for dependency types it implements

24

25

26

## Usage Examples

27

28

### Basic Autowiring

29

30

```scala

31

import com.softwaremill.macwire.*

32

33

class DatabaseAccess()

34

class SecurityFilter()

35

class UserFinder(databaseAccess: DatabaseAccess, securityFilter: SecurityFilter)

36

class UserStatusReader(userFinder: UserFinder)

37

38

// Creates all dependencies automatically

39

val userStatusReader = autowire[UserStatusReader]()

40

```

41

42

Generates equivalent code:

43

```scala

44

val userStatusReader = {

45

val wiredDatabaseAccess = new DatabaseAccess()

46

val wiredSecurityFilter = new SecurityFilter()

47

val wiredUserFinder = new UserFinder(wiredDatabaseAccess, wiredSecurityFilter)

48

val wiredUserStatusReader = new UserStatusReader(wiredUserFinder)

49

wiredUserStatusReader

50

}

51

```

52

53

### Providing Instance Dependencies

54

55

```scala

56

import java.io.Closeable

57

58

class DataSource(jdbcConn: String) extends Closeable { def close() = () }

59

class DatabaseAccess(ds: DataSource)

60

class UserFinder(databaseAccess: DatabaseAccess)

61

62

// Provide pre-configured DataSource instance

63

val dataSource = new DataSource("jdbc:postgresql://localhost/mydb")

64

val userFinder = autowire[UserFinder](dataSource)

65

```

66

67

### Using Factory Functions

68

69

```scala

70

class ConfiguredService(config: Config)

71

72

// Use function to create dependency

73

val createService = () => new ConfiguredService(loadConfig())

74

val someService = autowire[SomeServiceUsingConfiguredService](createService)

75

```

76

77

### Using Class Dependencies

78

79

```scala

80

trait Logger

81

class ConsoleLogger extends Logger

82

class FileLogger extends Logger

83

class Service(logger: Logger)

84

85

// Specify which Logger implementation to use

86

val service = autowire[Service](classOf[ConsoleLogger])

87

```

88

89

90

### Complex Dependency Scenarios

91

92

```scala

93

class EmailService(smtpHost: String, port: Int)

94

class NotificationService(emailService: EmailService, logger: Logger)

95

class UserService(notificationService: NotificationService)

96

97

class AppConfig {

98

val smtpHost = "smtp.example.com"

99

val smtpPort = 587

100

val logger = new ConsoleLogger()

101

}

102

103

val appConfig = new AppConfig()

104

105

// Combine multiple dependency sources

106

val userService = autowire[UserService](

107

appConfig.smtpHost,

108

appConfig.smtpPort,

109

appConfig.logger

110

)

111

```

112

113

## Behavior and Characteristics

114

115

### Dependency Resolution Order

116

117

1. **Explicit Dependencies**: Parameters passed to `autowire` are checked first

118

2. **Constructor/Apply Methods**: Missing dependencies are created using public constructors or companion object `apply` methods

119

3. **Recursive Creation**: The process repeats for nested dependencies

120

121

### Type Matching

122

123

- Dependencies are matched by exact type

124

- Subtype relationships are not automatically resolved

125

- Generic types are matched with full type parameters

126

127

### Error Conditions

128

129

- **Missing Dependencies**: Compile-time error if a required dependency cannot be created or provided

130

- **Ambiguous Dependencies**: Error when multiple instances of the same type are provided

131

- **Unsupported Types**: Primitive types and certain Scala built-in types cannot be autowired

132

- **Cyclic Dependencies**: Detected and reported at compile time

133

134

### Compilation Requirements

135

136

- Only available in Scala 3

137

- Requires the macros library as a "provided" dependency

138

- All wiring resolution happens at compile time with zero runtime overhead