Skip to content

LLCFreedom-Space/fs-dependency-injection

fs-dependency-injection

Swift Version License GitHub release (with filter) Read the Docs example workflow example workflow example workflow codecov

Dependency injection (DI) is a design pattern that allows components to be loosely coupled by providing their dependencies as arguments. This can make code more modular, reusable, and testable.

The FSDependencyInjection library provides a simple and efficient way to implement DI in Swift.

Installation

To install the DependencyInjection library, add the following dependency to your Package.swift file:

dependencies: [
    .package(url: "https://github.com/LLCFreedom-Space/fs-dependency-injection.git", from: "1.0.0")
]

Usage

To use the DependencyInjection library, you first need to create a Container instance. The shared property provides a shared instance of the container that can be used throughout your application.

let container = Container.shared

Once you have a Container instance, you can register services with it. To register a service, you call the register() method. The register() method takes two arguments: the type of the service to register and a factory closure that creates an instance of the service.

class MyService { ... }

// Use factory

container.register(
    to: MyService.self,
    factory: { container in
        MyService()
    }
)

// Or via value

container.register(
    to: MyService.self,
    value: MyService()
)

The factory closure can access the container to resolve other dependencies.

To resolve a service from the container, you call the resolve() method. The resolve() method takes one argument: the type of the service to resolve.

let myService = container.resolve()

The resolve() method returns an optional value. If the service is not registered, the method returns nil.

Lifetime of Services

The lifetime of a service instance can be either transient or singleton. Transient instances are created anew each time they are resolved. Singleton instances are shared across all requests.

The lifetime of a service instance can be specified when it is registered with the container. The InstanceType enum defines two cases:

  • transient: The service instance is transient.
  • singleton: The service instance is a singleton.
class MyService { ... }

container.register(
    to: MyService.self,
    instanceType: .singleton
)

Property Wrappers

The DependencyInjection library also provides a property wrapper, @Inject, that can be used to inject dependencies into properties.

To use the @Inject property wrapper, you simply annotate the property with the wrapper. The wrapper will automatically inject the appropriate service instance into the property.

class MyViewController {
    @Inject var myService: MyService
}

In this example, the myService property in MyViewController will be injected with a singleton instance of MyService.

Example

Here is an example of how to use the DependencyInjection library:

class MyService {
    var name: String

    init(name: String) {
        self.name = name
    }
}

class MyViewController {
    @Inject var myService: MyService

    init() {
        myService.name = "Hello, world!"
    }

    func printName() {
        print(myService.name)
    }
}

let viewController = MyViewController()
viewController.printName()

This code will print the following output:

Hello, world!

Links

LLC Freedom Space – @LLCFreedomSpacesupport@freedomspace.company

Distributed under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3. See LICENSE.md for more information.

GitHub