Giter Site home page Giter Site logo

kawoou / deli Goto Github PK

View Code? Open in Web Editor NEW
135.0 135.0 8.0 1.15 MB

Deli is an easy-to-use Dependency Injection(DI).

License: MIT License

Swift 96.91% Ruby 0.60% HTML 1.89% Shell 0.60%
automatically command-line dependency-injection di inversion-of-control swift

deli's People

Contributors

cruisediary avatar erjanmx avatar kawoou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deli's Issues

Support multiple module.

In case, projects are managed by integrating them into separate modules.

Don't instantiated the DeliFactory class yourself.
Provides load methods via AppContext.

AppDelegate.swift:

import Deli
import OtherModule1
import OtherModule2

class AppDelegate {
    var window: UIWindow?

    let container = AppContext.load([
        DeliFactory.self,
        OtherModule1.DeliFactory.self,
        OtherModule2.DeliFactory.self
    ])

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        return true
    }
}

Support dependency injection for without lifecycle management.

The lifecycle of UICollectionViewCell is managed by UICollectionView.
In such a case, dependency injection must be possible.

This rules in #4:

class PhotoCollectionViewCell: UICollectionViewCell, Injectable {
    func inject(_ userService: Dependency<UserService>, _ userID: Argument<String>) {
        ...
    }
}

//-----------------------------------------------------------

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    ...
    cell.inject(with: (userID))
    ...
    return cell
}

We temporarily used the name "Injectable". Is there a good naming?

Support multiple buld target on deli.yml

I want to change to this format.

deli.yml:

target:
  - Sample
  - GitHubSearch
  - Survey

config:
  Sample:
    include:
      - Tests/DeliTests/DeliSample
    exclude:
      - Tests/DeliTests/DeliSample/DeliFactory.swift
    output: Tests/DeliTests/DeliSample
  GitHubSearch:
    project: Examples/GitHubSearch/GitHubSearch
    output: GitHubSearch/DeliFactory.swift
  Survey:
    project: Examples/Survey/Survey.xcodeproj
    output: Survey/DeliFactory.swift

Improved loading flow for ModuleFactory

The Test Mode function is inconvenient for writing test code.
Therefore, want to improve the ModuleFactory so that it can be simplified.

class SomeControllerTests: QuickSpec {
    override func spec() {
        super.spec()

        var sut: SomeController!

        var mockUserService: MockUserService!
        var mockFriendService: MockFriendService!

        let testModule = ModuleFactory()
        testModule.register(MockUserService.self) { MockUserService() }
            .link(UserService.self)
        testModule.register(MockFriendService.self) { MockFriendService() }
            .link(FriendService.self)

        beforeEach {
            AppContext.shared.load(testModule, priority: .high)
        }
        afterEach {
            AppContext.shared.reset()
            AppContext.shared.unload(testModule)
        }

        describe("SomeController") {
            beforeEach {
                sut = AppContext.shared.get(SomeController.self)
                mockUserService = AppContext.shared.get(MockUserService.self)
                mockFriendService = AppContext.shared.get(MockFriendService.self)
            }
            ...
        }
    }
}

Support "always" and "weak" scope.

  • Always: Instantiated in advance even if not used at launch.
  • weak: It is similar to "singleton" but uses "weak" as a caching strategy. (If not used, will be released on memory)

Support configuration property.

How to build

Change the Deli configuration file or include it via command line.

application-dev.properties:

environment: dev
server:
    url: https://dev.example.com/

deli.yml:

target:
- App

config:
  App:
    - project: App
    - properties:
      - Resources/Common/*.properties
      - Resources/application-dev.properties # override

command line:

deli build \
  --property "Resource/application-dev.properties" \
  --property "Resources/Common/*.properties"

How to use

1. Package

ServerConfig.swift:

struct ServerConfig: ConfigProperty {
    let target: String = "server"
    let url: String
}

NetworkManager.swift:

final class NetworkManager: Autowired {
    let serverUrl: String

    required init(_ config: ServerConfig) {
        serverUrl = config.url
    }
}

2. Single (without Validate)

NetworkManager.swift:

final class NetworkManager {
    let serverUrl = AppContext.getProperty("server.url") ?? ""
}

3. Single (with Validate)

NetworkManager.swift:

final class NetworkManager: Inject {
    let serverUrl = InjectProperty("server.url")
}

4. Qualifier on Constructor Injection

UserService.swift:

final class UserService: Autowired {
    required init(_/*environment*/ network: NetworkProvider) {
    }
}

5. Qualifier on Inject

LibraryFactory.swift:

final class LibraryFactory: Inject {
    func getBooks() -> [Book] {
        return Inject([Book].self, qualifierBy: "environment")
    }
}

Reference

Support qualifier in Autowired.

I want to modify it so that we can specify qualifier in Autowired protocol.
But, a good way to easy-use has not thought yet.

Support user-arguments.

Payload:

struct UserPayload: Payload {
    let userID: String

    required init(with argument: (userID: String)) {
        self.userID = argument.userID
    }
}

AutowiredFactory:

class UserViewModel: AutowiredFactory {
    required init(
        _ testService: TestService,
        _ userService: UserService,
        payload: UserPayload
    ) {
        self.testService = testService
        self.userID = payload.userID
    }
}

//-----------------------------------------------------------

class UserView: UIView, Inject {
    let viewModel: UserViewModel

    init(userID: String) {
        viewModel = Inject(UserViewModel.self, with: (userID: userID))
    }
}

LazyAutowiredFactory:

class UserViewModel: LazyAutowiredFactory {
    func inject(
        _ testService: TestService,
        _ userService: UserService,
        payload: UserPayload
    ) {
        self.testService = testService
        self.userID = payload.userID
    }
    required init() {}
}

//-----------------------------------------------------------

class UserView: UIView, Inject {
    let viewModel: UserViewModel

    init(userID: String) {
        viewModel = Inject(UserViewModel.self, with: (userID: userID))
    }
}

If specified as a Factory, automatically operates as a prototype scope.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.