Closed jrogccom closed 3 years ago
First, you might find the following interesting InjectableDemo, as I've been looking into compile-time safety. (Which generated this article in turn.)
Looking at the code, I can see a couple of issues right off the bat.
1) My biggest problem with this approach is that simple protocol conformance doesn't guarantee that the code will actually register a service of the correct class. I mean, if your class is going to conform you should do so. But there's no guarantee that you will actually do so.
2) It adds more boilerplate per registration.
extension XYZLazyService2: LazyRegistrable {
static func register(to resolver: Resolver, name: Resolver.Name?, args: Any?) {
resolver.register { XYZLazyService2() }
}
}
That's 4 lines of largely boilerplate code vs the 1 that's actually needed. Now, I could easily forgive that if it solved the compile-time safety issue, but it doesn't. And I think attempting to add protocol conformance leads us down the associated type issue I mention in the article.
Let me think about it.
Definitely agreed, it does not enforce registration. I was thinking we could have a method that returns a "RegistrationRequest" struct that wraps the closure of the Service to be produced and encapsulates the possible options applied as well. I'll modify this draft to reflect that.
In regards to boilerplate - it's true that it creates additional boilerplate, but only if the user chooses to conform to the protocol. Basically, it creates an alternative to adding everything on registerAllServices.
Thanks for considering it. I'll definitely have a look at those articles as well.
LazyRegsitrable
protocol withstatic register(to container: Resolver)
enables lazy registration to a container upon resolution of the type. Would allow for decentralized registration, which could in turn help avoid a crash whereupon one forgot to register the class or its implementations.Posting as Draft in hope of comments.