84 lines
2.1 KiB
Go
84 lines
2.1 KiB
Go
package di
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
var creatorMutex = sync.Mutex{}
|
|
var instanceMutex = sync.Mutex{}
|
|
var creators = make(map[string]func() any)
|
|
var instances = make(map[string]any)
|
|
|
|
// Injectable marks a constructor Function of a Struct for DI
|
|
func Injectable[T any](creator func() T) {
|
|
creatorMutex.Lock()
|
|
defer creatorMutex.Unlock()
|
|
creators[getSelector[T]()] = func() any {
|
|
return creator()
|
|
}
|
|
}
|
|
|
|
func Replace[T any](creator func() T, identifier ...string) {
|
|
Injectable(creator)
|
|
selector := getSelector[T]()
|
|
instanceSelector := getSelector[T](identifier...)
|
|
cre, creatorExists := creators[selector]
|
|
if !creatorExists {
|
|
return
|
|
}
|
|
createdInstance, instanceCreated := cre().(T)
|
|
if instanceCreated {
|
|
instanceMutex.Lock()
|
|
defer instanceMutex.Unlock()
|
|
instances[instanceSelector] = createdInstance
|
|
}
|
|
}
|
|
|
|
// Inject gets or create a Instance of the Struct used the Injectable constructor Function
|
|
func Inject[T any](identifier ...string) T {
|
|
var nilResult T
|
|
selector := getSelector[T]()
|
|
instanceSelector := getSelector[T](identifier...)
|
|
_, instanceExists := instances[instanceSelector].(T)
|
|
if !instanceExists {
|
|
creator, creatorExists := creators[selector]
|
|
if !creatorExists {
|
|
return nilResult
|
|
}
|
|
createdInstance, instanceCreated := creator().(T)
|
|
if instanceCreated {
|
|
instanceMutex.Lock()
|
|
defer instanceMutex.Unlock()
|
|
instance, instanceExists := instances[instanceSelector].(T)
|
|
if instanceExists {
|
|
return instance
|
|
}
|
|
instances[instanceSelector] = createdInstance
|
|
}
|
|
}
|
|
return instances[instanceSelector].(T)
|
|
}
|
|
|
|
func Destroy[T any](identifier ...string) {
|
|
instanceMutex.Lock()
|
|
defer instanceMutex.Unlock()
|
|
instanceSelector := getSelector[T](identifier...)
|
|
delete(instances, instanceSelector)
|
|
}
|
|
|
|
func getSelector[T any](identifier ...string) string {
|
|
var def T
|
|
typeName := ""
|
|
typeOf := reflect.TypeOf(def)
|
|
if typeOf != nil {
|
|
typeName = typeOf.String()
|
|
} else {
|
|
typeName = reflect.TypeOf((*T)(nil)).Elem().String()
|
|
}
|
|
additionalKey := strings.Join(identifier, "_")
|
|
return fmt.Sprintf("%s_%s", typeName, additionalKey)
|
|
}
|