Skip to content

Commit

Permalink
Feature/activate unregistered type (#9)
Browse files Browse the repository at this point in the history
* Adds new activate.go resolver module
* Renames test types and changes interface visibility
  • Loading branch information
matzefriedrich authored Jul 19, 2024
1 parent 2fd6730 commit 3be652b
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 13 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ 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).

## [Unreleased]

### Added

* Adds the `Activate[T]` method which can resolve an instance from an unregistered activator func


## v0.5.0 - 2024-07-16

Expand Down
44 changes: 44 additions & 0 deletions internal/tests/activate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package tests

import (
"context"
"github.com/matzefriedrich/parsley/pkg/registration"
"github.com/matzefriedrich/parsley/pkg/resolving"
"github.com/stretchr/testify/assert"
"testing"
)

func Test_Activate_resolve_unknown_service_type_using_resolve_options(t *testing.T) {

// Arrange
registry := registration.NewServiceRegistry()
_ = registration.RegisterTransient(registry, newBar)

sut := resolving.NewResolver(registry)
scopedContext := resolving.NewScopedContext(context.Background())

// Act
actual, err := resolving.Activate[bar0](sut, scopedContext, newFooWithBar)

// Assert
assert.NoError(t, err)
assert.NotNil(t, actual)
}

type fooWithBar struct {
bar bar0
}

type bar struct{}

type foo0 interface{}

type bar0 interface{}

func newFooWithBar(bar bar0) foo0 {
return &fooWithBar{bar: bar}
}

func newBar() bar0 {
return &bar{}
}
26 changes: 13 additions & 13 deletions internal/tests/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,37 @@ func Test_Resolver_Resolve_returns_err_if_circular_dependency_detected(t *testin

// Arrange
registry := registration.NewServiceRegistry()
_ = registration.RegisterTransient(registry, newFoo)
_ = registration.RegisterTransient(registry, newBar)
_ = registration.RegisterTransient(registry, newFooRequiringBar)
_ = registration.RegisterTransient(registry, newBarRequiringFoo)

r := resolving.NewResolver(registry)

scope := resolving.NewScopedContext(context.Background())

// Act
_, err := r.Resolve(scope, registration.ServiceType[Foo0]())
_, err := r.Resolve(scope, registration.ServiceType[fooBar]())

// Assert
assert.ErrorIs(t, err, types.ErrCircularDependencyDetected)
assert.ErrorIs(t, err, types.ErrCannotBuildDependencyGraph)
}

type foo0 struct {
bar Bar0
type fooRequiresBar struct {
bar barFoo
}

type Foo0 interface{}
type fooBar interface{}

type bar0 struct {
foo Foo0
type barRequiresFoo struct {
foo fooBar
}

type Bar0 interface{}
type barFoo interface{}

func newFoo(bar Bar0) Foo0 {
return &foo0{bar: bar}
func newFooRequiringBar(bar barFoo) fooBar {
return &fooRequiresBar{bar: bar}
}

func newBar(foo Foo0) Bar0 {
return &bar0{foo: foo}
func newBarRequiringFoo(foo fooBar) barFoo {
return &barRequiresFoo{foo: foo}
}
39 changes: 39 additions & 0 deletions pkg/resolving/activate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package resolving

import (
"context"
"github.com/matzefriedrich/parsley/pkg/registration"
"github.com/matzefriedrich/parsley/pkg/types"
)

func Activate[T any](resolver types.Resolver, ctx context.Context, activatorFunc any, options ...types.ResolverOptionsFunc) (T, error) {

var nilInstance T

lifetimeScope := types.LifetimeTransient
registration, registrationErr := registration.CreateServiceRegistration(activatorFunc, lifetimeScope)
if registrationErr != nil {
return nilInstance, types.NewResolverError("failed to create instance of unregistered type", types.WithCause(registrationErr))
}

serviceType := registration.ServiceType()
resolveActivatorFuncOption := func(registry types.ServiceRegistry) error {
return registry.Register(activatorFunc, lifetimeScope)
}

services, err := resolver.ResolveWithOptions(ctx, serviceType, resolveActivatorFuncOption)
if err != nil {
return nilInstance, err
}

if len(services) == 1 {
compatible, ok := services[0].(T)
if ok {
return compatible, nil
}
} else if len(services) > 1 {
return nilInstance, types.NewResolverError(types.ErrorAmbiguousServiceInstancesResolved)
}

return nilInstance, types.NewResolverError(types.ErrorCannotResolveService)
}

0 comments on commit 3be652b

Please sign in to comment.