add Replace di Instance

This commit is contained in:
admin 2025-06-23 20:39:18 +02:00
parent d90ca3f007
commit 24e307bd32
3 changed files with 198 additions and 0 deletions

124
README.md
View File

@ -4,6 +4,8 @@ Go Dependency Injection with Generics
## Example
### Struct
configuration.go
```go
@ -97,3 +99,125 @@ func main() {
println(msgService.Welcome())
}
```
### Interface
message_service.go
```go
package main
import "git.apihub24.de/admin/generic-di"
func init() {
di.Injectable(newMessageService)
}
type IMessageService interface {
Welcome() string
}
type messageService struct {
greeter *Greeter
}
func NewMessageService() IMessageService {
return &messageService{
// here was the Greeter from greeter.go injected
greeter: di.Inject[*Greeter](),
}
}
func (ctx *messageService) Welcome() string {
return ctx.greeter.Greet()
}
```
main.go
```go
package main
import di "git.apihub24.de/admin/generic-di"
func main() {
msgService := di.Inject[IMessageService]()
// prints the message "Hello, Markus"
println(msgService.Welcome())
}
```
## Replace Instance
services/message_service.go
```go
package services
import "git.apihub24.de/admin/generic-di"
func init() {
di.Injectable(newMessageService)
}
type IMessageService interface {
Welcome() string
}
type messageService struct {
greeter *Greeter
}
func NewMessageService() IMessageService {
return &messageService{
// here was the Greeter from greeter.go injected
greeter: di.Inject[*Greeter](),
}
}
func (ctx *messageService) Welcome() string {
return ctx.greeter.Greet()
}
```
main.go
```go
package main
import di "git.apihub24.de/admin/generic-di"
func main() {
msgService := di.Inject[services.IMessageService]()
// prints the message "Hello, Markus"
println(msgService.Welcome())
}
```
message_service_test.go
```go
package services_test
func init() {
// replace the instance of IMessageService with the Mock
di.Replace(newMessageServiceMock)
}
type messageServiceMock struct {}
func newMessageServiceMock() services.IMessageService {
return &messageServiceMock{}
}
func (svc *messageServiceMock) Welcome() string {
return "Hello, Mock"
}
func TestMessageServiceMocking(t *testing.T) {
service := di.Inject[services.IMessageService]()
if service.Welcome() != "Hello, Mock" {
t.Errorf("expect Hello, Mock but get %s", service.Welcome())
}
}
```

View File

@ -21,6 +21,22 @@ func Injectable[T any](creator func() T) {
}
}
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

View File

@ -13,6 +13,7 @@ func init() {
di.Injectable(newMessageService)
di.Injectable(newConfiguration)
di.Injectable(newGreetingService)
di.Injectable(newBasicOverridableService)
}
type (
@ -30,8 +31,33 @@ type (
Greeting() string
TakeID() string
}
overridableService interface {
GetInstanceID() string
GetValue() string
}
basicOverridableService struct {
id string
}
basicOverridableServiceMock struct {
id string
}
)
func newBasicOverridableService() overridableService {
return &basicOverridableService{
id: uuid.NewString(),
}
}
func newBasicOverridableServiceMock() overridableService {
return &basicOverridableServiceMock{
id: uuid.NewString(),
}
}
func newConfiguration() *configuration {
return &configuration{}
}
@ -53,6 +79,22 @@ func newMessageService() *messageService {
}
}
func (ctx *basicOverridableService) GetInstanceID() string {
return ctx.id
}
func (ctx *basicOverridableService) GetValue() string {
return "i am original"
}
func (ctx *basicOverridableServiceMock) GetInstanceID() string {
return ctx.id
}
func (ctx *basicOverridableServiceMock) GetValue() string {
return "i am mock"
}
func (ctx *configuration) GetUserName() string {
return "Markus"
}
@ -134,6 +176,22 @@ func TestTryInterface_MultipleInstances(t *testing.T) {
}
}
func TestOverwriteInjectable(t *testing.T) {
basic := di.Inject[overridableService]()
basicID := basic.GetInstanceID()
if basic.GetValue() != "i am original" {
t.Errorf("wrong service instance get")
}
di.Replace(newBasicOverridableServiceMock)
basic = di.Inject[overridableService]()
if basic.GetInstanceID() == basicID {
t.Errorf("basic and newOne are the same instance")
}
if basic.GetValue() != "i am mock" {
t.Errorf("service not overwritten")
}
}
func TestDestroy(t *testing.T) {
_ = di.Inject[textService]("a")
di.Destroy[textService]("a")