Skip to content

Add variadic-generic Service.init overload #78

@bbrk24

Description

@bbrk24

Checklist

Problem

When a single type has a lot of dependencies, the registration gets long and repetitive, and is fragile to changing the init:

Service(.transient, FooProtocol.self) { r in
  Foo(
    bar: r.resolve(),
    baz: r.resolve(),
    qux: r.resolve(),
    // ...
  )
}

Feature Request

As of Swift 5.9 (Xcode 15), we can add an overload like this:

#if swift(>=5.9)
extension Service {
    @available(swift 5.9)
    public init<TRegistration, each TDependency>(
        _ scope: Scope,
        _ type: TRegistration.Type,
        name: String? = nil,
        _ callback: @escaping (repeat each TDependency) -> TRegistration
    ) {
        self.init(scope, type, name: name) { (r: Resolver) in
            callback(repeat r.resolve((each TDependency).self))
        }
    }
}
#endif

each TDependency represents a "parameter pack"; the number of generic arguments to this initializer is variable. With this overload, one can say:

Service(.transient, FooProtocol.self, Foo.init)

I tested this locally and it works without confusing the compiler on existing registrations. However, I tested this on Linux, so I had to disable everything related to SwiftUI/Combine. I don't have a Mac to test those parts myself.

Value

The Factory.register blocks would become shorter, making them easier to read and write. Most callbacks passed to the Service are just an initializer.

Something similar could be done for MultitypeService.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions