hmlongco / Resolver

Swift Ultralight Dependency Injection / Service Locator framework
MIT License
2.14k stars 188 forks source link

[Draft] Lazy Registration #120

Closed jrogccom closed 3 years ago

jrogccom commented 3 years ago

LazyRegsitrable protocol with static 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.

hmlongco commented 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.

jrogccom commented 3 years ago

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.