> ## Documentation Index
> Fetch the complete documentation index at: https://genai.codewithsiva.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Dependency Injection

> Supplying dependencies from outside an object

## What is Dependency Injection?

**Dependency Injection (DI)** is a design pattern where an object **receives its dependencies from an external source** instead of creating them itself.

A **dependency** is any object another object requires to perform its work.

Examples:

* Database
* Repository
* Logger
* Email Service
* Configuration

## Without Dependency Injection

The object creates its own dependency.

```python theme={null}
class Engine:
    pass

class Car:
    def __init__(self):
        self.engine = Engine()      # Tight coupling
```

**Problems**

* Tight coupling
* Hard to test
* Difficult to replace dependencies

## With Dependency Injection

The dependency is supplied from outside.

```python theme={null}
class Engine:
    pass

class Car:
    def __init__(self, engine):
        self.engine = engine
```

Usage:

```python theme={null}
engine = Engine()
car = Car(engine)
```

Now `Car` only uses the engine—it doesn't create it.

## Real-world Example: Repository & Service

### Without DI

```python theme={null}
class StudentRepository:
    def get_all(self):
        return ["Alice", "Bob"]


class StudentService:
    def __init__(self):
        self.repo = StudentRepository()

    def list_students(self):
        return self.repo.get_all()
```

### With DI

```python theme={null}
class StudentRepository:
    def get_all(self):
        return ["Alice", "Bob"]


class StudentService:
    def __init__(self, repository):
        self.repo = repository

    def list_students(self):
        return self.repo.get_all()
```

Usage:

```python theme={null}
repo = StudentRepository()
service = StudentService(repo)

print(service.list_students())
```

Later, we can replace the repository without changing the service.

```python theme={null}
service = StudentService(MockStudentRepository())
```

## Benefits

* Loose coupling
* Easier testing
* Better maintainability
* Easily replace implementations
* More reusable code

## Types of Dependency Injection

### Constructor Injection (Most Common)

```python theme={null}
class UserService:
    def __init__(self, database):
        self.database = database
```

### Setter Injection

```python theme={null}
service.set_database(database)
```

### Method Injection

```python theme={null}
service.get_user(database)
```

## FastAPI Example

FastAPI automatically performs dependency injection.

```python theme={null}
from fastapi import Depends

def get_repository():
    return StudentRepository()

@app.get("/students")
def get_students(
    repo = Depends(get_repository)
):
    return repo.get_all()
```

A more realistic example using a service:

```python theme={null}
def get_repository():
    return StudentRepository()

def get_service(
    repo = Depends(get_repository)
):
    return StudentService(repo)

@app.get("/students")
def get_students(
    service = Depends(get_service)
):
    return service.list_students()
```

## Summary

Dependency Injection is a technique where:

* Objects **receive** their dependencies instead of creating them.
* Components remain **loosely coupled**.
* Dependencies can be replaced easily.
* Testing becomes much simpler.
* Frameworks like **FastAPI**, **Spring Boot**, and **ASP.NET Core** automate dependency injection.
