# Swift Dependency Injection with Swinject

As in most loosely coupled projects where we have big chains of dependencies.  [Swinject](https://github.com/Swinject/Swinject)  makes it simple and easy to do dependency injection. We’re going to use it in combination with the Swifts new property wrapper

Let’s say we have a 3 layer dependency:


![1_DtFTj2qdMmgDfeGCyR_jCw.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1634841087978/nY12llx6I.png)

Of course, we can use good old manual dependency injection as follows:

```swift
class TodoListViewModel: ObservableObject {
    var getTodosUseCase = GetTodosUseCase(
        repo: TodoRepositoryImpl(
            dataSource: TodoDataSourceImpl()
        )
    )
....
}
```

```swift
class TodoListViewModel: ObservableObject {
    @Inject
    private var getTodosUseCase : GetTodos
....
}
```

This would allow us to control the external dependencies by simply decorating the property with the Inject annotation and specifying the interface.

So the first thing is the @Inject annotation. In Swift, we use a property wrapper. Since Swift 5.1, the property wrapper feature enables us to attach logic directly to the property itself. Here we create a property wrapper called “Inject” that will automatically assign something to the prop


```swift
@propertyWrapper
struct Inject<I> {
    let wrappedValue: I
    init() {
        //Resolve the interface to an implementation.
        self.wrappedValue = Resolver.shared.resolve(I.self)
    }
}
```

Let’s build the resolver

```swift
class Resolver {
    static let shared = Resolver()
    
    //get the IOC container
    private var container = buildContainer() 
    
    func resolve<T>(_ type: T.Type) -> T {
        container.resolve(T.self)!
    }
}
```

All we now need is an IOC container. Let’s use Swinject to build one to resolve all interfaces to their respective implementations:

```swift
import Swinject
func buildContainer() -> Container {
    let container = Container()
    container.register(GetTodos.self) { _  in
        return GetTodosUseCase()
    }.inObjectScope(.container)
    container.register(TodoDataSource.self) { _  in
        return TodoMockDataSourceImpl()
    }.inObjectScope(.container)
    container.register(TodoRepository.self) { _  in
        return TodoRepositoryImpl()
    }.inObjectScope(.container)
    return container
}
```


