我正在尝试为依赖注入创建一个属性包装器:
@propertyWrapper struct Dependency<T> {
private(set) var wrappedValue: T
init() {
wrappedValue = Dependencies.shared.resolve()
}
}
final class Dependencies {
static let shared = Dependencies()
private var dependencies = [String: AnyObject]()
func register<T, P>(_ dependency: T, as: P.Type) {
let key = String(describing: P.self)
dependencies[key] = dependency as AnyObject
}
func resolve<T>() -> T {
let key = String(describing: T.self)
let dependency = dependencies[key] as? T
precondition(dependency != nil, "No dependency found for (key)! must register a dependency before resolve.")
return dependency!
}
}
目的是注册一个符合协议的对象,然后根据协议类型查找。
例如:
protocol Foo {
func foo() -> String
}
class Bar: Foo {
func foo() -> String {
"Hello World!"
}
}
Dependencies.shared.register(Bar(), as: Foo.self)
struct Test {
@Dependency var a: Foo
}
let t = Test()
print(t.a.foo())
正常工作-打印"Hello World!">
但是,我也可以这样做:
Dependencies.shared.register("not a Bar", as: Foo.self)
和前提条件爆发,因为String不符合Foo。
我要做的是约束func register<T, P>(_ dependency: T, as: P.Type)
使T必须符合p
像register<T: P, P>(_ dependency: T, as: P.Type)
这样的东西-显然不起作用。
这可能吗?
我认为这个改变一定符合你的期望:
func register<T>(_ dependency: T, as dependencyType: T.Type) {
let key = String(describing: dependencyType)
dependencies[key] = dependency as AnyObject
}
(其余代码保持不变)
那么这行困扰你不编译(Cannot convert value of type 'String' to expected argument type 'Bar'
):
Dependencies.shared.register("not a Bar", as: Bar.self)