CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-rodi

Implementation of dependency injection for Python 3

Overall
score

92%

Overview
Eval results
Files

factory-registration.mddocs/

Factory Registration

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.

Capabilities

Singleton Factory Registration

Registers a factory function that creates singleton services - the factory is called once and the result is cached.

def add_singleton_by_factory(self, factory: FactoryCallableType, return_type: Optional[Type] = None) -> Container:
    """
    Register a singleton service created by a factory function.
    
    Args:
        factory: Factory function to create the service instance
        return_type: Expected return type (inferred from factory if not provided)
        
    Returns:
        Container instance for method chaining
    """

Transient Factory Registration

Registers a factory function that creates transient services - the factory is called every time the service is resolved.

def add_transient_by_factory(self, factory: FactoryCallableType, return_type: Optional[Type] = None) -> Container:
    """
    Register a transient service created by a factory function.
    
    Args:
        factory: Factory function to create service instances
        return_type: Expected return type (inferred from factory if not provided)
        
    Returns:
        Container instance for method chaining
    """

Scoped Factory Registration

Registers a factory function that creates scoped services - the factory is called once per scope and the result is cached within that scope.

def add_scoped_by_factory(self, factory: FactoryCallableType, return_type: Optional[Type] = None) -> Container:
    """
    Register a scoped service created by a factory function.
    
    Args:
        factory: Factory function to create service instances
        return_type: Expected return type (inferred from factory if not provided)
        
    Returns:
        Container instance for method chaining
    """

Factory Function Types

Rodi supports three different factory function signatures for maximum flexibility:

No Arguments Factory

Simple factory functions that take no arguments and create service instances.

FactoryCallableNoArguments = Callable[[], Any]

Usage example:

def create_database_service():
    connection_string = get_connection_string_from_config()
    return DatabaseService(connection_string)

container.add_singleton_by_factory(create_database_service, DatabaseService)

Single Argument Factory (Scope)

Factory functions that take an ActivationScope parameter for context-aware service creation.

FactoryCallableSingleArgument = Callable[[ActivationScope], Any]

Usage example:

def create_request_logger(scope: ActivationScope):
    request_context = scope.get(RequestContext)
    return Logger(f"Request-{request_context.request_id}")

container.add_scoped_by_factory(create_request_logger, Logger)

Two Arguments Factory (Scope and Type)

Factory functions that take both an ActivationScope and the requested Type for advanced factory scenarios.

FactoryCallableTwoArguments = Callable[[ActivationScope, Type], Any]

Usage example:

def create_generic_repository(scope: ActivationScope, entity_type: Type):
    db_context = scope.get(DatabaseContext)
    return GenericRepository(db_context, entity_type)

container.add_scoped_by_factory(create_generic_repository)

Factory Type Union

Combined type hint for all supported factory function signatures.

FactoryCallableType = Union[FactoryCallableNoArguments, FactoryCallableSingleArgument, FactoryCallableTwoArguments]

Factory Registration Patterns

Configuration-based Services

Use factories to create services that depend on external configuration:

def create_email_service():
    config = load_email_config()
    if config.provider == "smtp":
        return SmtpEmailService(config.smtp_settings)
    elif config.provider == "sendgrid":
        return SendGridEmailService(config.api_key)
    else:
        raise ValueError(f"Unknown email provider: {config.provider}")

container.add_singleton_by_factory(create_email_service, EmailService)

Environment-specific Services

Create different service implementations based on environment:

def create_storage_service():
    if os.getenv("ENVIRONMENT") == "production":
        return S3StorageService(
            bucket=os.getenv("S3_BUCKET"),
            access_key=os.getenv("AWS_ACCESS_KEY")
        )
    else:
        return LocalFileStorageService(path="./storage")

container.add_singleton_by_factory(create_storage_service, StorageService)

Complex Initialization

Use factories for services requiring complex initialization logic:

def create_cache_service(scope: ActivationScope):
    config = scope.get(CacheConfiguration)
    
    # Complex setup logic
    cache = RedisCache(config.connection_string)
    cache.set_serializer(JsonSerializer())
    cache.configure_eviction_policy(config.eviction_policy)
    
    # Setup cache warming
    if config.warm_cache:
        cache.warm_up(config.warm_up_keys)
    
    return cache

container.add_singleton_by_factory(create_cache_service, CacheService)

Conditional Service Creation

Create services conditionally based on runtime state:

def create_audit_service(scope: ActivationScope):
    user = scope.get(CurrentUser)
    
    if user.requires_audit_logging:
        return DatabaseAuditService(scope.get(AuditDatabase))
    else:
        return NoOpAuditService()

container.add_scoped_by_factory(create_audit_service, AuditService)

Install with Tessl CLI

npx tessl i tessl/pypi-rodi

docs

aliases-names.md

container-configuration.md

factory-registration.md

index.md

scoped-services.md

service-resolution.md

tile.json