From fd95efea185d04054e3e6898807a193e12da6721 Mon Sep 17 00:00:00 2001 From: Matthias Friedrich <1573457+matzefriedrich@users.noreply.github.com> Date: Sun, 1 Sep 2024 22:00:27 +0200 Subject: [PATCH] Allows registration of struct dependencies (#18) * Allows registration of struct dependencies --- CHANGELOG.md | 7 ++ ...egistry_register_struct_dependency_test.go | 90 +++++++++++++++++++ pkg/registration/activator.go | 1 + pkg/registration/service_registration.go | 2 + pkg/resolving/resolver.go | 1 + pkg/types/service_type.go | 1 + 6 files changed, 102 insertions(+) create mode 100644 internal/tests/registration/registry_register_struct_dependency_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 911ce3e..073a163 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v0.8.3] - 2024-09-01 + +### Fixed + +* Allows registration of (immutable) struct dependencies + + ## [v0.8.2] - 2024-08-29 ### Fixed diff --git a/internal/tests/registration/registry_register_struct_dependency_test.go b/internal/tests/registration/registry_register_struct_dependency_test.go new file mode 100644 index 0000000..eb81d1d --- /dev/null +++ b/internal/tests/registration/registry_register_struct_dependency_test.go @@ -0,0 +1,90 @@ +package registration + +import ( + "context" + "github.com/matzefriedrich/parsley/pkg/registration" + "github.com/matzefriedrich/parsley/pkg/resolving" + "github.com/matzefriedrich/parsley/pkg/types" + "github.com/stretchr/testify/assert" + "testing" +) + +func Test_Register_struct_dependency(t *testing.T) { + + // Arrange + registry := registration.NewServiceRegistry() + + config := someConfig{b: true} + registryErr := registration.RegisterInstance[someConfig](registry, config) + + resolver := resolving.NewResolver(registry) + ctx := resolving.NewScopedContext(context.Background()) + + // Act + actual, err := resolving.ResolveRequiredService[someConfig](resolver, ctx) + + // Arrange + assert.NoError(t, registryErr) + assert.NoError(t, err) + assert.True(t, actual.b) +} + +func Test_Register_service_with_struct_dependency(t *testing.T) { + + // Arrange + registry := registration.NewServiceRegistry() + registry.Register(newAppWithStructDependency, types.LifetimeTransient) + + config := someConfig{b: true} + registryErr := registration.RegisterInstance[someConfig](registry, config) + + resolver := resolving.NewResolver(registry) + ctx := resolving.NewScopedContext(context.Background()) + + // Act + actual, err := resolving.ResolveRequiredService[*appWithStructDependency](resolver, ctx) + + // Arrange + assert.NoError(t, registryErr) + assert.NoError(t, err) + assert.NotNil(t, actual) + assert.True(t, actual.config.b) +} + +func Test_Register_immutable_service_with_struct_dependency(t *testing.T) { + + // Arrange + registry := registration.NewServiceRegistry() + registry.Register(newImmutableAppWithStructDependency, types.LifetimeTransient) + + config := someConfig{b: true} + registryErr := registration.RegisterInstance[someConfig](registry, config) + + resolver := resolving.NewResolver(registry) + ctx := resolving.NewScopedContext(context.Background()) + + // Act + actual, err := resolving.ResolveRequiredService[appWithStructDependency](resolver, ctx) + + // Arrange + assert.NoError(t, registryErr) + assert.NoError(t, err) + assert.NotNil(t, actual) + assert.True(t, actual.config.b) +} + +type someConfig struct { + b bool +} + +type appWithStructDependency struct { + config someConfig +} + +func newAppWithStructDependency(config someConfig) *appWithStructDependency { + return &appWithStructDependency{config: config} +} + +func newImmutableAppWithStructDependency(config someConfig) appWithStructDependency { + return appWithStructDependency{config: config} +} diff --git a/pkg/registration/activator.go b/pkg/registration/activator.go index 1a675ca..9d14d27 100644 --- a/pkg/registration/activator.go +++ b/pkg/registration/activator.go @@ -15,6 +15,7 @@ func CreateServiceActivatorFrom[T any](instance T) (func() T, error) { case reflect.Func: case reflect.Interface: case reflect.Pointer: + case reflect.Struct: default: return nil, types.NewRegistryError(types.ErrorActivatorFunctionInvalidReturnType) } diff --git a/pkg/registration/service_registration.go b/pkg/registration/service_registration.go index 82585aa..e487c82 100644 --- a/pkg/registration/service_registration.go +++ b/pkg/registration/service_registration.go @@ -113,6 +113,8 @@ func CreateServiceRegistration(activatorFunc any, lifetimeScope types.LifetimeSc fallthrough case reflect.Pointer: fallthrough + case reflect.Struct: + fallthrough case reflect.Interface: requiredTypes := info.ParameterTypes() return newServiceRegistration(serviceType, lifetimeScope, value, requiredTypes...), nil diff --git a/pkg/resolving/resolver.go b/pkg/resolving/resolver.go index c4111bd..d2de070 100644 --- a/pkg/resolving/resolver.go +++ b/pkg/resolving/resolver.go @@ -21,6 +21,7 @@ func ResolveRequiredServices[T any](resolver types.Resolver, ctx context.Context case reflect.Interface: case reflect.Pointer: case reflect.Slice: + case reflect.Struct: default: return []T{}, types.NewResolverError(types.ErrorActivatorFunctionInvalidReturnType) } diff --git a/pkg/types/service_type.go b/pkg/types/service_type.go index 64b5a5e..1690910 100644 --- a/pkg/types/service_type.go +++ b/pkg/types/service_type.go @@ -53,6 +53,7 @@ func ServiceTypeFrom(t reflect.Type) ServiceType { case reflect.Slice: t = t.Elem() isList = true + case reflect.Struct: default: panic("unsupported type: " + t.String()) }