所以我试图使用泛型和协议一致性来创建一个小的依赖注入容器。但是我在编译时遇到了一些麻烦。
我想知道是否有一位快速的专家可以告诉我这是什么问题。
import Foundation
protocol Service: NSObjectProtocol {
init()
}
protocol ServicesType {
func add<S: Service>(service: S.Type)
func get<S: Service>() throws -> S
}
class Services: ServicesType {
var services: [Service.Type] = []
func add<S: Service>(service: S.Type) {
if services.contains(where: { service -> Bool in return service == service }) { return }
services.append(service)
}
func get<S: Service>() throws -> S {
guard let first = services.first(where: { service -> Bool in return service == service }) else { throw ServicesTypeError.notFound }
return first.init() as! S
}
}
enum ServicesTypeError: Error {
case notFound
}
当我尝试编译下面的行时,无法推断通用参数'S'是错误消息
let creditCardService: CreditCardServiceType = try self.services.get()
protocol CreditCardServiceType : Service {
var cards: [CreditCard] { get }
}
class CreditCardService: CreditCardServiceType {
internal required init() {}
var cards: [CreditCard] = []
}
答案 0 :(得分:0)
在Playground中进行这项工作需要一些修改,但这似乎有效。
如果我是对的(粗体),
let creditCardService: **CreditCardServiceType** = try self.services.get()
需要:
let creditCardService: **CreditCardService** = try self.services.get()
完整代码:
import Foundation
protocol Service: NSObjectProtocol {
init()
}
protocol ServicesType {
func add<S: Service>(service: S.Type)
func get<S: Service>() throws -> S
}
class Services: ServicesType {
var services: [Service.Type] = []
func add<S: Service>(service: S.Type) {
if services.contains(where: { service -> Bool in return service == service }) { return }
services.append(service)
}
func get<S: Service>() throws -> S {
guard let first = services.first(where: { service -> Bool in return service == service }) else { throw ServicesTypeError.notFound }
return first.init() as! S
}
}
enum ServicesTypeError: Error {
case notFound
}
class CreditCard {
}
protocol CreditCardServiceType : Service {
var cards: [CreditCard] { get }
}
class CreditCardService: NSObject, CreditCardServiceType {
required override init() {
super.init()
}
var cards: [CreditCard] = []
}
let services = Services()
services.add(service: CreditCardService.self)
let creditCardService: CreditCardService = try services.get()
答案 1 :(得分:-1)
好的,我最终得到的是以下内容。不像我想要的那样安全,但足够好。
import Foundation
protocol Service: NSObjectProtocol {
init()
}
protocol ServicesType {
func add<S: Service>(service: S.Type) throws
func get<S>() throws -> S
}
class Services: ServicesType {
var services: [Service.Type] = []
func add<S: Service>(service: S.Type) throws {
if services.contains(where: { existing -> Bool in return existing == service }) { throw ServicesTypeError.allReadyAdded}
services.append(service)
}
func get<S>() throws -> S {
guard let first = services.first(where: { existing -> Bool in return existing is S }) else { throw ServicesTypeError.notFound }
return first.init() as! S
}
}
enum ServicesTypeError: Error {
case allReadyAdded
case notFound
}
用法:
try self.services.add(service: ProfileService.self)
let profileService: ProfileServiceType = try self.services.get()