0
# Factory Registration
1
2
Advanced service registration using factory functions for complex instantiation scenarios. Supports different factory signatures, service lifestyles, and provides flexibility for services that require custom initialization logic.
3
4
## Capabilities
5
6
### Singleton Factory Registration
7
8
Registers a factory function that creates singleton services - the factory is called once and the result is cached.
9
10
```python { .api }
11
def add_singleton_by_factory(self, factory: FactoryCallableType, return_type: Optional[Type] = None) -> Container:
12
"""
13
Register a singleton service created by a factory function.
14
15
Args:
16
factory: Factory function to create the service instance
17
return_type: Expected return type (inferred from factory if not provided)
18
19
Returns:
20
Container instance for method chaining
21
"""
22
```
23
24
### Transient Factory Registration
25
26
Registers a factory function that creates transient services - the factory is called every time the service is resolved.
27
28
```python { .api }
29
def add_transient_by_factory(self, factory: FactoryCallableType, return_type: Optional[Type] = None) -> Container:
30
"""
31
Register a transient service created by a factory function.
32
33
Args:
34
factory: Factory function to create service instances
35
return_type: Expected return type (inferred from factory if not provided)
36
37
Returns:
38
Container instance for method chaining
39
"""
40
```
41
42
### Scoped Factory Registration
43
44
Registers a factory function that creates scoped services - the factory is called once per scope and the result is cached within that scope.
45
46
```python { .api }
47
def add_scoped_by_factory(self, factory: FactoryCallableType, return_type: Optional[Type] = None) -> Container:
48
"""
49
Register a scoped service created by a factory function.
50
51
Args:
52
factory: Factory function to create service instances
53
return_type: Expected return type (inferred from factory if not provided)
54
55
Returns:
56
Container instance for method chaining
57
"""
58
```
59
60
## Factory Function Types
61
62
Rodi supports three different factory function signatures for maximum flexibility:
63
64
### No Arguments Factory
65
66
Simple factory functions that take no arguments and create service instances.
67
68
```python { .api }
69
FactoryCallableNoArguments = Callable[[], Any]
70
```
71
72
Usage example:
73
74
```python
75
def create_database_service():
76
connection_string = get_connection_string_from_config()
77
return DatabaseService(connection_string)
78
79
container.add_singleton_by_factory(create_database_service, DatabaseService)
80
```
81
82
### Single Argument Factory (Scope)
83
84
Factory functions that take an ActivationScope parameter for context-aware service creation.
85
86
```python { .api }
87
FactoryCallableSingleArgument = Callable[[ActivationScope], Any]
88
```
89
90
Usage example:
91
92
```python
93
def create_request_logger(scope: ActivationScope):
94
request_context = scope.get(RequestContext)
95
return Logger(f"Request-{request_context.request_id}")
96
97
container.add_scoped_by_factory(create_request_logger, Logger)
98
```
99
100
### Two Arguments Factory (Scope and Type)
101
102
Factory functions that take both an ActivationScope and the requested Type for advanced factory scenarios.
103
104
```python { .api }
105
FactoryCallableTwoArguments = Callable[[ActivationScope, Type], Any]
106
```
107
108
Usage example:
109
110
```python
111
def create_generic_repository(scope: ActivationScope, entity_type: Type):
112
db_context = scope.get(DatabaseContext)
113
return GenericRepository(db_context, entity_type)
114
115
container.add_scoped_by_factory(create_generic_repository)
116
```
117
118
### Factory Type Union
119
120
Combined type hint for all supported factory function signatures.
121
122
```python { .api }
123
FactoryCallableType = Union[FactoryCallableNoArguments, FactoryCallableSingleArgument, FactoryCallableTwoArguments]
124
```
125
126
## Factory Registration Patterns
127
128
### Configuration-based Services
129
130
Use factories to create services that depend on external configuration:
131
132
```python
133
def create_email_service():
134
config = load_email_config()
135
if config.provider == "smtp":
136
return SmtpEmailService(config.smtp_settings)
137
elif config.provider == "sendgrid":
138
return SendGridEmailService(config.api_key)
139
else:
140
raise ValueError(f"Unknown email provider: {config.provider}")
141
142
container.add_singleton_by_factory(create_email_service, EmailService)
143
```
144
145
### Environment-specific Services
146
147
Create different service implementations based on environment:
148
149
```python
150
def create_storage_service():
151
if os.getenv("ENVIRONMENT") == "production":
152
return S3StorageService(
153
bucket=os.getenv("S3_BUCKET"),
154
access_key=os.getenv("AWS_ACCESS_KEY")
155
)
156
else:
157
return LocalFileStorageService(path="./storage")
158
159
container.add_singleton_by_factory(create_storage_service, StorageService)
160
```
161
162
### Complex Initialization
163
164
Use factories for services requiring complex initialization logic:
165
166
```python
167
def create_cache_service(scope: ActivationScope):
168
config = scope.get(CacheConfiguration)
169
170
# Complex setup logic
171
cache = RedisCache(config.connection_string)
172
cache.set_serializer(JsonSerializer())
173
cache.configure_eviction_policy(config.eviction_policy)
174
175
# Setup cache warming
176
if config.warm_cache:
177
cache.warm_up(config.warm_up_keys)
178
179
return cache
180
181
container.add_singleton_by_factory(create_cache_service, CacheService)
182
```
183
184
### Conditional Service Creation
185
186
Create services conditionally based on runtime state:
187
188
```python
189
def create_audit_service(scope: ActivationScope):
190
user = scope.get(CurrentUser)
191
192
if user.requires_audit_logging:
193
return DatabaseAuditService(scope.get(AuditDatabase))
194
else:
195
return NoOpAuditService()
196
197
container.add_scoped_by_factory(create_audit_service, AuditService)
198
```
199
200