-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #201 from cashapp/bradfol/autoregistercollection-m…
…ainactor Reimplement `autoregisterIntoCollection()` methods with `@MainActor`
- Loading branch information
Showing
5 changed files
with
882 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
158 changes: 158 additions & 0 deletions
158
Sources/Knit/ServiceCollection/Container+ServiceCollection.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// | ||
// NOTICE: | ||
// | ||
// This file is generated from Container+ServiceCollection.erb by ERB. | ||
// Do NOT modify it directly. | ||
// Instead, modify Container+ServiceCollection.erb and run `Scripts/gencode`. | ||
// | ||
<% type_count = 20 %> | ||
|
||
import Foundation | ||
|
||
extension Container { | ||
|
||
/// Registers a service factory into a collection. | ||
/// | ||
/// Usage: | ||
/// ``` | ||
/// let container = Container() | ||
/// container.addBehavior(ServiceCollector()) | ||
/// container.registerIntoCollection(Animal.self) { _ in Cat(...) } | ||
/// container.registerIntoCollection(Animal.self) { _ in Dog(...) } | ||
/// | ||
/// let animals = resolver.resolveCollection(Animal.self) | ||
/// print(animals.entries) // [Cat, Dog] | ||
/// ``` | ||
/// - Parameters: | ||
/// - service: The service type to register. | ||
/// - factory: The closure to specify how the service type is resolved with the dependencies of the type. | ||
/// It is invoked when the ``Container`` needs to instantiate the instance. | ||
/// It takes a ``Resolver`` to inject dependencies to the instance, | ||
/// and returns the instance of the component type for the service. | ||
/// - Returns: The registered service entry. | ||
@discardableResult | ||
public func registerIntoCollection<Service>( | ||
_ service: Service.Type, | ||
factory: @escaping @MainActor (Resolver) -> Service | ||
) -> ServiceEntry<Service> { | ||
self.register( | ||
service, | ||
name: makeUniqueCollectionRegistrationName(), | ||
factory: { resolver in | ||
MainActor.assumeIsolated { | ||
return factory(resolver) | ||
} | ||
} | ||
) | ||
} | ||
|
||
/// Registers a service factory into a collection. | ||
/// | ||
/// Usage: | ||
/// ``` | ||
/// let container = Container() | ||
/// container.addBehavior(ServiceCollector()) | ||
/// container.autoregisterIntoCollection(Animal.self, initializer: Cat.init) | ||
/// container.autoregisterIntoCollection(Animal.self, initializer: Dog.init) | ||
/// | ||
/// let animals = resolver.resolveCollection(Animal.self) | ||
/// print(animals.entries) // [Cat, Dog] | ||
/// ``` | ||
/// - Parameters: | ||
/// - service: The service type to register. | ||
/// - initializer: Initializer of the registered service. | ||
/// - Returns: The registered service entry. | ||
@discardableResult | ||
public func autoregisterIntoCollection<Service>( | ||
_ service: Service.Type, | ||
initializer: @escaping @MainActor (()) -> Service | ||
) -> ServiceEntry<Service> { | ||
let initClosure = { | ||
MainActor.assumeIsolated { | ||
initializer(()) | ||
} | ||
} | ||
return self.autoregister( | ||
service, | ||
name: makeUniqueCollectionRegistrationName(), | ||
initializer: initClosure | ||
) | ||
} | ||
|
||
/// Registers a service factory into a collection. | ||
/// | ||
/// Usage: | ||
/// ``` | ||
/// let container = Container() | ||
/// container.addBehavior(ServiceCollector()) | ||
/// container.autoregisterIntoCollection(Animal.self, initializer: Cat.init) | ||
/// container.autoregisterIntoCollection(Animal.self, initializer: Dog.init) | ||
/// | ||
/// let animals = resolver.resolveCollection(Animal.self) | ||
/// print(animals.entries) // [Cat, Dog] | ||
/// ``` | ||
/// - Parameters: | ||
/// - service: Registered service type. | ||
/// - initializer: Initializer of the registered service. | ||
/// - Returns: The registered service entry. | ||
@discardableResult | ||
public func autoregisterIntoCollection<Service, T1>( | ||
_ service: Service.Type, | ||
initializer: @escaping @MainActor ((T1)) -> Service | ||
) -> ServiceEntry<Service> { | ||
let initClosure = { (arg: (T1)) in | ||
MainActor.assumeIsolated { | ||
initializer((arg)) | ||
} | ||
} | ||
return self.autoregister( | ||
service, | ||
name: makeUniqueCollectionRegistrationName(), | ||
initializer: initClosure | ||
) | ||
} | ||
|
||
<% (2..type_count).each do |i| %> | ||
<% types = (1..i).map { |n| "T#{n}" }.join(", ") %> | ||
<% args = (0..i-1).map { |n| "args.#{n}" }.join(", ") %> | ||
/// Registers a service factory into a collection. | ||
/// | ||
/// Usage: | ||
/// ``` | ||
/// let container = Container() | ||
/// container.addBehavior(ServiceCollector()) | ||
/// container.autoregisterIntoCollection(Animal.self, initializer: Cat.init) | ||
/// container.autoregisterIntoCollection(Animal.self, initializer: Dog.init) | ||
/// | ||
/// let animals = resolver.resolveCollection(Animal.self) | ||
/// print(animals.entries) // [Cat, Dog] | ||
/// ``` | ||
/// - Parameters: | ||
/// - service: Registered service type. | ||
/// - initializer: Initializer of the registered service. | ||
/// - Returns: The registered service entry. | ||
@discardableResult | ||
public func autoregisterIntoCollection<Service, <%= types %>>( | ||
_ service: Service.Type, | ||
initializer: @escaping @MainActor ((<%= types %>)) -> Service | ||
) -> ServiceEntry<Service> { | ||
let initClosure = { (args: (<%= types %>)) in | ||
MainActor.assumeIsolated { | ||
initializer((<%= args %>)) | ||
} | ||
} | ||
return self.autoregister( | ||
service, | ||
name: makeUniqueCollectionRegistrationName(), | ||
initializer: initClosure | ||
) | ||
} | ||
<% end %> | ||
|
||
// MARK: - Private Methods | ||
|
||
private func makeUniqueCollectionRegistrationName() -> String { | ||
"\(collectionRegistrationPrefix)-\(UUID().uuidString)" | ||
} | ||
|
||
} |
Oops, something went wrong.