Closed Narayane closed 6 years ago
@Narayane can you just register it with a tag?
When it is needed just cast it to how you will use it?
@iAmNaz Not sure to understand your words, can you give an example relative to my case.
I think my aim is a little bit different, if i understand well named definitions examples. I don't want to have different implementations for a given protocol (dependant of an environment or whatever). I want to be sure thanks to Dip than only one instance of a concrete class will be used to resolve 3 different singletons
Assuming this is your concrete class, correct?
class MyDataSource: AuthProtocol, RealTimeDatabaseProtocol, FileStorageProtocol {}
Registration:
container.register(tag: "DataSourceTag") { MyDataSource() as MyDataSource }
OR
container.register(.singleton) { MyDataSource() as MyDataSource }
Usage:
let dataSource = try container.resolve(tag: "DataSourceTag" ) as MyDataSource
OR
let dataSource = try container.resolve( ) as MyDataSource
Use your datasource as normal and if you need it to be of some protocol then just cast it
let auth = dataSource as! AuthProtocol
@Narayane try to use type forwarding for this - https://github.com/AliSoftware/Dip/wiki/type-forwarding
@iAmNaz named definitions should be used to distinguish registrations of the same type which return different implementations depending on label, in this case its required to resolve different types to the same instance, so even if named definitions would work that would be a not a good solution IMO
We have a solution to perform registartion chaining.
Assuming the Class
conforms to Protocol1
and Protocol2
:
container.register {
Class()
}.reregister {
$0 as Protocol1
}.reregister {
$0 as Protocol2
}
with another scope:
container.register(.singleton) {
Class()
}.reregister {
$0 as Protocol1
}.reregister {
$0 as Protocol2
}
Implementation:
public final class ContainerPromise<T, U> {
let container: DependencyContainer
let definition: Definition<T, U>
init(
_ definition: Definition<T, U>,
_ container: DependencyContainer)
{
self.definition = definition
self.container = container
}
@discardableResult public func reregister<T2>(
factory: @escaping (T) -> T2)
-> ContainerPromise<T, U>
{
container.register(
resolvable: T.self,
factory: factory
)
return self
}
}
public extension DependencyContainer {
func promise<T, U>(_ definition: Definition<T, U>) -> ContainerPromise<T, U> {
return ContainerPromise(definition, self)
}
}
public extension DependencyContainer {
@discardableResult public func register<T, R>(
_ scope: ComponentScope = .shared,
resolvable: R.Type,
type: T.Type = T.self,
tag: DependencyTagConvertible? = nil,
factory: @escaping (R) -> T)
-> ContainerPromise<T, ()>
{
let definition = register(scope, type: type, tag: tag) { [weak self] () -> T in
guard let strongSelf = self else {
fatalError(
"Can't register object with type \(T.self) " +
"because container deallocated"
)
}
let definition = factory((try strongSelf.resolve() as R))
return definition
}
return promise(definition)
}
}
Hi,
I have created 3 protocols for evolutivity and testability reasons. For now, I have only one concrete class which implements these protocols.
I declare this in my DI configuration:
self.register(.singleton) { MyDataSource() as AuthProtocol }
self.register(.singleton) { MyDataSource() as RealTimeDatabaseProtocol }
self.register(.singleton) { MyDataSource() as FileStorageProtocol }
Will MyDataSource be instantiated only one time by Dip? If not, how can I do this?
Thanks.