如何在我的工厂解析器中使用相同的抽象接口注册 2 个依赖项?
How can I register 2 dependencies with the same abstract interface in my factory resolver?
我有一个依赖容器,看起来像这样 -
public protocol DependencyContainer {
typealias FactoryClosure = (Self) -> AnyObject
func register<Service>(type: Service.Type, closure: @escaping FactoryClosure)
func resolve<Service>(type: Service.Type) -> Service
}
public final class CoreDependencyContainer: DependencyContainer {
private var services: Dictionary<ObjectIdentifier, FactoryClosure> = [:]
public func register<Service>(type: Service.Type, closure: @escaping FactoryClosure) {
services[ObjectIdentifier(type)] = closure
}
public func resolve<Service>(type: Service.Type) -> Service {
if let service = services[ObjectIdentifier(type)]?(self) as? Service {
return service
}
preconditionFailure("Could not resolve service for \(type)")
}
}
我注册了一些服务如下:
dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
let httpClient = container.resolve(type: HTTPClient.self)
return RemoteImageDataLoader(client: httpClient)
})
但是我想注册2个符合抽象类型的服务RemoteImageDataLoader
。
dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
let httpClient = container.resolve(type: HTTPClient.self)
return RemoteImageDataLoader(client: httpClient)
})
dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
let httpClient = container.resolve(type: AuthenticatedHTTPClient.self)
return RemoteImageDataLoader(client: httpClient)
})
这显然行不通,因为第二个条目将替换 services
字典中的第一个条目。
我试图创建一个 typealias
来代替使用,但是这不起作用。
dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
let httpClient = container.resolve(type: HTTPClient.self)
return RemoteImageDataLoader(client: httpClient)
})
typealias AuthRemoteImageLoader = RemoteImageDataLoader
dependencies.register(type: AuthRemoteImageLoader.self, closure: { container in
let httpClient = container.resolve(type: AuthenticatedHTTPClient.self)
return RemoteImageDataLoader(client: httpClient)
})
在这种情况下如何注册第二个依赖项?
我想避免创建 2 个版本的 RemoteImageDataLoader
,因为唯一的区别是注入的 HTTPClient
实例。
当前它不起作用,因为您正在使用 ObjectIdentifier
作为字典中的关键字,typealias
不会更改。
你基本上是在注册同一个对象两次。
创建一个符合相同接口的空协议。您还需要扩展您的接口以符合新的空接口,否则您的 resolve
方法将抛出 preconditionFailure
protocol AuthRemoteImageLoader: RemoteImageDataLoader { }
extension RemoteImageDataLoader: AuthRemoteImageLoader { }
您还可以考虑使用泛型来指定正在使用的 HTTPClient
接口,并扩展 RemoteImageDataLoader
以根据客户端类型采取相应的行动。
我有一个依赖容器,看起来像这样 -
public protocol DependencyContainer {
typealias FactoryClosure = (Self) -> AnyObject
func register<Service>(type: Service.Type, closure: @escaping FactoryClosure)
func resolve<Service>(type: Service.Type) -> Service
}
public final class CoreDependencyContainer: DependencyContainer {
private var services: Dictionary<ObjectIdentifier, FactoryClosure> = [:]
public func register<Service>(type: Service.Type, closure: @escaping FactoryClosure) {
services[ObjectIdentifier(type)] = closure
}
public func resolve<Service>(type: Service.Type) -> Service {
if let service = services[ObjectIdentifier(type)]?(self) as? Service {
return service
}
preconditionFailure("Could not resolve service for \(type)")
}
}
我注册了一些服务如下:
dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
let httpClient = container.resolve(type: HTTPClient.self)
return RemoteImageDataLoader(client: httpClient)
})
但是我想注册2个符合抽象类型的服务RemoteImageDataLoader
。
dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
let httpClient = container.resolve(type: HTTPClient.self)
return RemoteImageDataLoader(client: httpClient)
})
dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
let httpClient = container.resolve(type: AuthenticatedHTTPClient.self)
return RemoteImageDataLoader(client: httpClient)
})
这显然行不通,因为第二个条目将替换 services
字典中的第一个条目。
我试图创建一个 typealias
来代替使用,但是这不起作用。
dependencies.register(type: RemoteImageDataLoader.self, closure: { container in
let httpClient = container.resolve(type: HTTPClient.self)
return RemoteImageDataLoader(client: httpClient)
})
typealias AuthRemoteImageLoader = RemoteImageDataLoader
dependencies.register(type: AuthRemoteImageLoader.self, closure: { container in
let httpClient = container.resolve(type: AuthenticatedHTTPClient.self)
return RemoteImageDataLoader(client: httpClient)
})
在这种情况下如何注册第二个依赖项?
我想避免创建 2 个版本的 RemoteImageDataLoader
,因为唯一的区别是注入的 HTTPClient
实例。
当前它不起作用,因为您正在使用 ObjectIdentifier
作为字典中的关键字,typealias
不会更改。
你基本上是在注册同一个对象两次。
创建一个符合相同接口的空协议。您还需要扩展您的接口以符合新的空接口,否则您的 resolve
方法将抛出 preconditionFailure
protocol AuthRemoteImageLoader: RemoteImageDataLoader { }
extension RemoteImageDataLoader: AuthRemoteImageLoader { }
您还可以考虑使用泛型来指定正在使用的 HTTPClient
接口,并扩展 RemoteImageDataLoader
以根据客户端类型采取相应的行动。