fix: reverted the bourbier done to DI, reflection is bad

This commit is contained in:
Florian Sylvain
2025-03-29 01:52:22 +01:00
parent 2292a8ef34
commit cb9a431488
+40 -101
View File
@@ -5,52 +5,13 @@ import (
"GoCMS/adapters/secondary/gateways/models" "GoCMS/adapters/secondary/gateways/models"
domainGateways "GoCMS/domain/gateways" domainGateways "GoCMS/domain/gateways"
"GoCMS/useCases" "GoCMS/useCases"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"reflect"
"runtime"
"github.com/glebarez/sqlite" "github.com/glebarez/sqlite"
"go.uber.org/dig"
"gorm.io/gorm" "gorm.io/gorm"
) )
type UseCaseDefinition struct {
Constructor interface{}
FieldName string
}
type RepositoryDefinition struct {
Constructor interface{}
Interface interface{}
}
var useCaseDefinitions = []UseCaseDefinition{
{useCases.NewCreatePostUseCase, "CreatePostUseCase"},
{useCases.NewGetPostUseCase, "GetPostUseCase"},
{useCases.NewListPostsUseCase, "ListPostsUseCase"},
{useCases.NewUpdatePostUseCase, "UpdatePostUseCase"},
{useCases.NewDeletePostUseCase, "DeletePostUseCase"},
{useCases.NewGetUserUseCase, "GetUserUseCase"},
{useCases.NewCreateUserUseCase, "CreateUserUseCase"},
{useCases.NewUpdateUserUseCase, "UpdateUserUseCase"},
{useCases.NewDeleteUserUseCase, "DeleteUserUseCase"},
{useCases.NewListUsersUseCase, "ListUsersUseCase"},
{useCases.NewGetPageUseCase, "GetPageUseCase"},
{useCases.NewSendMailUseCase, "SendMailUseCase"},
{useCases.NewCreateImageUseCase, "CreateImageUseCase"},
{useCases.NewDeleteImageUseCase, "DeleteImageUseCase"},
}
var repositoryDefinitions = []RepositoryDefinition{
{gateways.NewPostRepository, new(domainGateways.IPostRepository)},
{gateways.NewUserRepository, new(domainGateways.IUserRepository)},
{gateways.NewImageRepository, new(domainGateways.IImageRepository)},
{gateways.NewMailRepository, new(domainGateways.IMailRepository)},
{gateways.NewPageRepository, new(domainGateways.IPageRepository)},
}
type UseCases struct { type UseCases struct {
CreatePostUseCase *useCases.CreatePostUseCase CreatePostUseCase *useCases.CreatePostUseCase
GetPostUseCase *useCases.GetPostUseCase GetPostUseCase *useCases.GetPostUseCase
@@ -68,6 +29,14 @@ type UseCases struct {
DeleteImageUseCase *useCases.DeleteImageUseCase DeleteImageUseCase *useCases.DeleteImageUseCase
} }
type Repositories struct {
PostRepo domainGateways.IPostRepository
UserRepo domainGateways.IUserRepository
ImageRepo domainGateways.IImageRepository
MailRepo domainGateways.IMailRepository
PageRepo domainGateways.IPageRepository
}
var Container *UseCases var Container *UseCases
func getDb() *gorm.DB { func getDb() *gorm.DB {
@@ -79,75 +48,45 @@ func getDb() *gorm.DB {
if err != nil { if err != nil {
panic("Unable to open the database: " + err.Error()) panic("Unable to open the database: " + err.Error())
} }
return db
}
func InitContainer() { if err := db.AutoMigrate(&models.Post{}, &models.User{}); err != nil {
digContainer := dig.New()
database := getDb()
if err := database.AutoMigrate(&models.Post{}, &models.User{}); err != nil {
panic("Failed to migrate database: " + err.Error()) panic("Failed to migrate database: " + err.Error())
} }
if err := digContainer.Provide(func() *gorm.DB { return database }); err != nil { return db
panic("Failed to provide database: " + err.Error()) }
}
provideRepositories(digContainer) func initRepositories(db *gorm.DB) *Repositories {
return &Repositories{
for _, def := range useCaseDefinitions { PostRepo: gateways.NewPostRepository(db),
if err := digContainer.Provide(def.Constructor); err != nil { UserRepo: gateways.NewUserRepository(db),
funcName := runtime.FuncForPC(reflect.ValueOf(def.Constructor).Pointer()).Name() ImageRepo: gateways.NewImageRepository(db),
panic(fmt.Sprintf("Failed to provide %s: %v", funcName, err)) MailRepo: gateways.NewMailRepository(),
} PageRepo: gateways.NewPageRepository(),
}
constructorType := buildConstructorType()
constructor := reflect.MakeFunc(constructorType, buildUseCasesInstance)
if err := digContainer.Provide(constructor.Interface()); err != nil {
panic("Failed to provide container constructor: " + err.Error())
}
if err := digContainer.Invoke(func(useCases *UseCases) { Container = useCases }); err != nil {
panic("Unable to invoke container: " + err.Error())
} }
} }
func buildConstructorType() reflect.Type { func initUseCases(repos *Repositories) *UseCases {
var paramTypes []reflect.Type return &UseCases{
for _, def := range useCaseDefinitions { CreatePostUseCase: useCases.NewCreatePostUseCase(repos.PostRepo),
constructorType := reflect.TypeOf(def.Constructor) GetPostUseCase: useCases.NewGetPostUseCase(repos.PostRepo),
returnType := constructorType.Out(0) ListPostsUseCase: useCases.NewListPostsUseCase(repos.PostRepo),
paramTypes = append(paramTypes, returnType) UpdatePostUseCase: useCases.NewUpdatePostUseCase(repos.PostRepo),
} DeletePostUseCase: useCases.NewDeletePostUseCase(repos.PostRepo),
GetUserUseCase: useCases.NewGetUserUseCase(repos.UserRepo),
return reflect.FuncOf(paramTypes, []reflect.Type{reflect.TypeOf(&UseCases{})}, false) CreateUserUseCase: useCases.NewCreateUserUseCase(repos.UserRepo),
} UpdateUserUseCase: useCases.NewUpdateUserUseCase(repos.UserRepo),
DeleteUserUseCase: useCases.NewDeleteUserUseCase(repos.UserRepo),
func buildUseCasesInstance(args []reflect.Value) []reflect.Value { ListUsersUseCase: useCases.NewListUsersUseCase(repos.UserRepo),
container := &UseCases{} GetPageUseCase: useCases.NewGetPageUseCase(repos.PageRepo),
containerValue := reflect.ValueOf(container).Elem() SendMailUseCase: useCases.NewSendMailUseCase(repos.MailRepo),
CreateImageUseCase: useCases.NewCreateImageUseCase(repos.ImageRepo),
for i, arg := range args { DeleteImageUseCase: useCases.NewDeleteImageUseCase(repos.ImageRepo),
fieldName := useCaseDefinitions[i].FieldName
field := containerValue.FieldByName(fieldName)
if field.IsValid() && field.CanSet() {
field.Set(arg)
} else {
panic(fmt.Sprintf("Failed to set field %s", fieldName))
}
}
return []reflect.Value{reflect.ValueOf(container)}
}
func provideRepositories(container *dig.Container) {
for _, def := range repositoryDefinitions {
if err := container.Provide(def.Constructor, dig.As(def.Interface)); err != nil {
funcName := runtime.FuncForPC(reflect.ValueOf(def.Constructor).Pointer()).Name()
panic(fmt.Sprintf("Failed to provide repository %s: %v", funcName, err))
}
} }
} }
func InitContainer() {
db := getDb()
repos := initRepositories(db)
Container = initUseCases(repos)
}