Skip to content

Basic Examples

This section provides practical examples to help you get started with NexusDI.

Simple Service Example

from nexusdi import singleton, transient, inject, initialize

@singleton
class DatabaseService:
    def __init__(self):
        self.connection = "postgresql://localhost/myapp"

    def query(self, sql: str):
        return f"Executing: {sql} on {self.connection}"

@transient
class UserService:
    def __init__(self, db: DatabaseService):
        self.db = db

    def get_user(self, user_id: int):
        return self.db.query(f"SELECT * FROM users WHERE id = {user_id}")

@inject
def handle_user_request(user_service: UserService, user_id: int):
    return user_service.get_user(user_id)

# Initialize and use
initialize()
result = handle_user_request(user_id=123)
print(result)  # "Executing: SELECT * FROM users WHERE id = 123 on postgresql://localhost/myapp"

Configuration and Logging Example

from nexusdi import singleton, transient, initialize
import logging

@singleton
class ConfigService:
    def __init__(self):
        self.settings = {
            'debug': True,
            'database_url': 'postgresql://localhost/myapp',
            'log_level': 'INFO'
        }

    def get(self, key: str, default=None):
        return self.settings.get(key, default)

@singleton
class LoggerService:
    def __init__(self, config: ConfigService):
        self.config = config
        logging.basicConfig(level=config.get('log_level'))
        self.logger = logging.getLogger(__name__)

    def info(self, message: str):
        self.logger.info(message)

    def error(self, message: str):
        self.logger.error(message)

@transient
class EmailService:
    def __init__(self, config: ConfigService, logger: LoggerService):
        self.config = config
        self.logger = logger

    def send_email(self, to: str, subject: str):
        self.logger.info(f"Sending email to {to}: {subject}")
        if self.config.get('debug'):
            print(f"DEBUG: Email sent to {to}")
        return f"Email sent to {to}"

# Usage
initialize()

email_service = _container.resolve(EmailService)
email_service.send_email("user@example.com", "Welcome!")

Repository Pattern Example

from nexusdi import singleton, transient, initialize
from abc import ABC, abstractmethod

class IUserRepository(ABC):
    @abstractmethod
    def find_by_id(self, user_id: int):
        pass

    @abstractmethod
    def save(self, user):
        pass

@transient
class DatabaseUserRepository(IUserRepository):
    def __init__(self, db_service: DatabaseService):
        self.db = db_service

    def find_by_id(self, user_id: int):
        return {"id": user_id, "name": f"User{user_id}", "email": f"user{user_id}@example.com"}

    def save(self, user):
        print(f"Saving user: {user}")
        return user

@transient
class UserBusinessLogic:
    def __init__(self, user_repo: DatabaseUserRepository, email_service: EmailService):
        self.user_repo = user_repo
        self.email_service = email_service

    def create_user(self, name: str, email: str):
        user = {"name": name, "email": email, "id": 123}
        saved_user = self.user_repo.save(user)
        self.email_service.send_email(email, "Account Created")
        return saved_user

# Usage
initialize()
business_logic = _container.resolve(UserBusinessLogic)
user = business_logic.create_user("John Doe", "john@example.com")

Caching Example

from nexusdi import singleton, transient, initialize
import time

@singleton
class CacheService:
    def __init__(self):
        self.cache = {}
        self.ttl = 300  # 5 minutes

    def get(self, key: str):
        if key in self.cache:
            data, timestamp = self.cache[key]
            if time.time() - timestamp < self.ttl:
                return data
            else:
                del self.cache[key]
        return None

    def set(self, key: str, value):
        self.cache[key] = (value, time.time())

@transient
class DataService:
    def __init__(self, cache: CacheService, db: DatabaseService):
        self.cache = cache
        self.db = db

    def get_expensive_data(self, key: str):
        # Check cache first
        cached_data = self.cache.get(key)
        if cached_data:
            return cached_data

        # Expensive operation
        data = self.db.query(f"SELECT * FROM expensive_table WHERE key = '{key}'")
        self.cache.set(key, data)
        return data

# Usage
initialize()
data_service = _container.resolve(DataService)
result = data_service.get_expensive_data("user_123")

Event System Example

from nexusdi import singleton, transient, initialize

@singleton
class EventBus:
    def __init__(self):
        self.listeners = {}

    def subscribe(self, event_type: str, callback):
        if event_type not in self.listeners:
            self.listeners[event_type] = []
        self.listeners[event_type].append(callback)

    def publish(self, event_type: str, data):
        if event_type in self.listeners:
            for callback in self.listeners[event_type]:
                callback(data)

@singleton
class NotificationService:
    def __init__(self, event_bus: EventBus):
        self.event_bus = event_bus
        self.event_bus.subscribe('user_created', self.send_welcome_email)

    def send_welcome_email(self, user_data):
        print(f"Sending welcome email to {user_data['email']}")

@transient
class UserService:
    def __init__(self, event_bus: EventBus, user_repo: DatabaseUserRepository):
        self.event_bus = event_bus
        self.user_repo = user_repo

    def create_user(self, name: str, email: str):
        user = {"name": name, "email": email}
        saved_user = self.user_repo.save(user)

        # Publish event
        self.event_bus.publish('user_created', saved_user)
        return saved_user

# Usage
initialize()
user_service = _container.resolve(UserService)
user = user_service.create_user("Alice", "alice@example.com")

Testing Example

import pytest
from nexusdi import singleton, transient, _container, initialize

# Production services
@singleton
class DatabaseService:
    def query(self, sql: str):
        return f"Real database result: {sql}"

@transient
class UserService:
    def __init__(self, db: DatabaseService):
        self.db = db

    def get_user(self, user_id: int):
        return self.db.query(f"SELECT * FROM users WHERE id = {user_id}")

# Test setup
class MockDatabaseService:
    def query(self, sql: str):
        return f"Mock result: {sql}"

def test_user_service():
    # Override dependency for testing
    _container.register(MockDatabaseService, LifeCycle.SINGLETON)
    _container._dependencies[DatabaseService] = _container._dependencies[MockDatabaseService]

    user_service = _container.resolve(UserService)
    result = user_service.get_user(123)

    assert "Mock result" in result
    assert "SELECT * FROM users WHERE id = 123" in result

# Run test
initialize()
test_user_service()

Common Patterns

Factory Pattern

@singleton
class ServiceFactory:
    def __init__(self, config: ConfigService):
        self.config = config

    def create_email_service(self):
        provider = self.config.get('email_provider', 'smtp')
        if provider == 'smtp':
            return SMTPEmailService()
        elif provider == 'sendgrid':
            return SendGridEmailService()
        else:
            raise ValueError(f"Unknown email provider: {provider}")

@transient
class EmailSender:
    def __init__(self, factory: ServiceFactory):
        self.email_service = factory.create_email_service()

Strategy Pattern

@transient
class PaymentProcessor:
    def __init__(self, config: ConfigService):
        self.config = config
        self.strategies = {
            'credit_card': CreditCardPayment(),
            'paypal': PayPalPayment(),
            'bank_transfer': BankTransferPayment()
        }

    def process(self, amount: float, method: str):
        strategy = self.strategies.get(method)
        if not strategy:
            raise ValueError(f"Unsupported payment method: {method}")
        return strategy.process(amount)

These examples demonstrate common patterns and use cases for NexusDI in real applications. Each example shows how to properly structure your dependencies and use the injection system effectively.