hmlongco / Resolver

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

Add `.container` scope #131

Closed ZsoltMolnarMBH closed 2 years ago

ZsoltMolnarMBH commented 2 years ago

Introduction

This PR introduces a new registration scope: .container. Using this, services can now be registered as "Singleton within the container", with the added bonus of being able to reset the container specific cache any time.

Motivation

Projects where containers are used without static reference , commonly face the need to register a service with "Singleton within the container" scope. This is completely possible by using a user defined ResolverScopeCache instance during service registrations, provided that the user makes sure this instance has the same lifecycle as the container.

The goal is to make this common usecase easier to implement.

Proposed solution

Resolver instances now have a new property:

public final class Resolver {
    // ...
    public let cache = ResolverScopeCache()
    // ...
}

So each instance has its own cache to be used for the desired scope.

This container specific cache instance is then accessed via a new ResolverScope type, that acts as a proxy.

The container specific caches can be reset, by the user any time. If we want to ditch this feature, we only need to reduce the visiblity of the cache property below public.

Usage:

func assemble(container: Resolver) {
    container.register {
        return MyService()
    }.scope(.container)
}

Effect on API

The suggested solution is small and backward compatible.

nczoltan commented 2 years ago

We're using dynamic containers and having this feature could make our life much easier. Currently we have to maintain a cached scope with the same lifecycle as our container which is unnecessary boilerplate. I think this would be a nice addition.

ZsoltMolnarMBH commented 2 years ago

Hello! I updated the PR according to the comments, added unit test and documentation. Removed [Draft] flag.