77 lines
1.3 KiB
Go
77 lines
1.3 KiB
Go
package service
|
|
|
|
import (
|
|
"log"
|
|
"reflect"
|
|
"sync"
|
|
)
|
|
|
|
type Lifecycle = string
|
|
|
|
var (
|
|
Singleton Lifecycle = "singleton"
|
|
)
|
|
|
|
type Provider struct {
|
|
cb func() any
|
|
lifecycle Lifecycle
|
|
}
|
|
|
|
type Locator struct {
|
|
services map[string]Provider
|
|
cache map[string]any
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
func NewLocator() *Locator {
|
|
return &Locator{
|
|
services: make(map[string]Provider),
|
|
cache: make(map[string]any),
|
|
mutex: sync.RWMutex{},
|
|
}
|
|
}
|
|
|
|
func (l *Locator) setCache(key string, value any) {
|
|
l.cache[key] = value
|
|
}
|
|
|
|
func (l *Locator) getCache(key string) any {
|
|
return l.cache[key]
|
|
}
|
|
|
|
func Get[T any](locator *Locator) *T {
|
|
locator.mutex.RLock()
|
|
i := new(T)
|
|
t := reflect.TypeOf(i).String()
|
|
|
|
cached := locator.getCache(t)
|
|
|
|
if cached != nil {
|
|
locator.mutex.RUnlock()
|
|
return cached.(*T)
|
|
}
|
|
|
|
entry, ok := locator.services[t]
|
|
if !ok {
|
|
log.Fatalf("%s is not registered in the service locator", t)
|
|
}
|
|
cb := entry.cb().(*T)
|
|
locator.mutex.RUnlock()
|
|
locator.mutex.Lock()
|
|
if entry.lifecycle == Singleton {
|
|
locator.setCache(t, cb)
|
|
}
|
|
locator.mutex.Unlock()
|
|
return cb
|
|
}
|
|
|
|
func Set[T any](locator *Locator, lifecycle Lifecycle, value func() *T) {
|
|
t := reflect.TypeOf(value)
|
|
rt := t.Out(0)
|
|
locator.services[rt.String()] = Provider{
|
|
cb: func() any {
|
|
return value()
|
|
},
|
|
lifecycle: lifecycle,
|
|
}
|
|
}
|