使用 swinject 注册具有关联类型的协议时出现问题
Posted
技术标签:
【中文标题】使用 swinject 注册具有关联类型的协议时出现问题【英文标题】:Problem registering protocols with associated types using swinject 【发布时间】:2021-05-01 13:00:29 【问题描述】:我想开发一个使用核心数据和领域的存储库模式的应用程序。我想根据我的需要解决协议。目的是在程序集中注入一个通用的核心数据存储库/领域存储库协议。
这行出现问题 Protocol 'SleepRepositoryProtocol' can only be used as a generic constraint because it has Self or associated type requirements
func assemble(container: Container)
container.register(SleepRepositoryProtocol.self) r in
CoreDataSleepRepository(persistentContainer:r.resolve(NSPersistentContainer.self)!)
.inObjectScope(.container)
由于使用通用(关联类型)属性,我无法注入睡眠存储库协议。我该如何解决这个问题?
另外,非常感谢您的回复。它真的帮了我很多。我还有一个问题。
var 存储库:SleepRepositoryProtocol
var items: [SleepEntity]?
private let assembler: Assembler
init(assembler: Assembler)
self.assembler = assembler
repository = assembler.resolver.resolve(SleepRepositoryProtocol.self)!
这给了我错误“协议 'SleepRepositoryProtocol' 只能用作通用约束,因为它具有 Self 或关联的类型要求”,我不知道如何解决我的 SleepRepositoryProtocol。
【问题讨论】:
我从未使用过 swinject,但此错误意味着您无法使用具有关联类型的协议来实例化类型。相反,实例化符合它的特定类型。 【参考方案1】:这个错误很经典:
container.register(SleepRepositoryProtocol.self) r in
被禁止,因为SleepRepositoryProtocol
是Protocol with Associated Type。
您需要将assemble(container:)
方法设为通用并以这种方式声明,例如:
func assemble<Repository: SleepRepositoryProtocol>(container: Container, ofType type:Repository)
但由于它是 Swinject's Assembly Protocol 的一部分,因此不是一个选项,您需要找到另一个放置 Generic Type Constraint 的地方。
在您的情况下,它可以是封闭类型,例如:
class MyClass<Repository: SleepRepositoryProtocol>: Assembly
func assemble(container: Container)
container.register(Repository.self) r in
CoreDataSleepRepository(persistentContainer:r.resolve(NSPersistentContainer.self)!)
.inObjectScope(.container)
编辑
你不能只写:
var repository: SleepRepositoryProtocol
一旦您在协议中添加associatedtype
,您就可以永远将它像普通类型一样仅作为Generic Type Constraint
如果我用你的其他属性更新MyClass
:
class MyClass<Repository: SleepRepositoryProtocol>: Assembly
var repository: Repository
var items: [SleepEntity]?
private let assembler: Assembler
init(assembler: Assembler)
self.assembler = assembler
repository = assembler.resolver.resolve(Repository.self)!
func assemble(container: Container)
container.register(Repository.self) r in
CoreDataSleepRepository(persistentContainer:r.resolve(NSPersistentContainer.self)!)
.inObjectScope(.container)
【讨论】:
非常感谢您的回复。它真的帮了我很多。我对此还有一个问题。这给了我错误,我不知道如何解决我的 SleepRepositoryProtocol。 var repository: RepositoryProtocol var items: [SleepEntity]? private let assembler: Assembler init(assembler: Assembler) self.assembler = assembler repository = assembler.resolver.resolve(RepositoryProtocol.self)! . 很难在评论中阅读。你应该编辑你的问题,或者更好地开始另一个问题 非常感谢您的回复。我已经更新了我的睡眠存储库,并且没有在其上使用泛型。这解决了我的问题,注射效果非常好。 太棒了。我会说,作为一项规则,您应该投票赞成有用的答案并接受为您提供最佳解决方案的答案;)以上是关于使用 swinject 注册具有关联类型的协议时出现问题的主要内容,如果未能解决你的问题,请参考以下文章
Swinject:生成任何对象的实例(对于未注册的对象、ViewModel 等...)