mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
fix: simplify DI implementation
Signed-off-by: Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
@@ -17,8 +17,6 @@
|
||||
package erasure
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
A "github.com/IBM/fp-go/array"
|
||||
"github.com/IBM/fp-go/errors"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
@@ -41,37 +39,61 @@ func itemProviderToMap(p Provider) map[string][]ProviderFactory {
|
||||
return R.Singleton(p.Provides().Id(), A.Of(p.Factory()))
|
||||
}
|
||||
|
||||
var missingProviderError = F.Flow4(
|
||||
Dependency.String,
|
||||
errors.OnSome[string]("no provider for dependency [%s]"),
|
||||
IOE.Left[any, error],
|
||||
F.Constant1[InjectableFactory, IOE.IOEither[error, any]],
|
||||
var (
|
||||
// missingProviderError returns a ProviderFactory that fails due to a missing dependency
|
||||
missingProviderError = F.Flow4(
|
||||
Dependency.String,
|
||||
errors.OnSome[string]("no provider for dependency [%s]"),
|
||||
IOE.Left[any, error],
|
||||
F.Constant1[InjectableFactory, IOE.IOEither[error, any]],
|
||||
)
|
||||
|
||||
emptyMulti any = A.Empty[any]()
|
||||
|
||||
// emptyMultiDependency returns a ProviderFactory for an empty, multi dependency
|
||||
emptyMultiDependency = F.Constant1[Dependency](F.Constant1[InjectableFactory](IOE.Of[error](emptyMulti)))
|
||||
|
||||
// handleMissingProvider covers the case of a missing provider. It either
|
||||
// returns an error or an empty multi value provider
|
||||
handleMissingProvider = F.Flow2(
|
||||
F.Ternary(isMultiDependency, emptyMultiDependency, missingProviderError),
|
||||
F.Constant[ProviderFactory],
|
||||
)
|
||||
|
||||
// mergeItemProviders is a monoid for item provider factories
|
||||
mergeItemProviders = R.UnionMonoid[string](A.Semigroup[ProviderFactory]())
|
||||
|
||||
// mergeProviders is a monoid for provider factories
|
||||
mergeProviders = R.UnionLastMonoid[string, ProviderFactory]()
|
||||
|
||||
// collectItemProviders create a provider map for item providers
|
||||
collectItemProviders = F.Flow2(
|
||||
A.FoldMap[Provider](mergeItemProviders)(itemProviderToMap),
|
||||
R.Map[string](itemProviderFactory),
|
||||
)
|
||||
|
||||
// collectProviders collects non-item providers
|
||||
collectProviders = F.Flow2(
|
||||
A.Map(providerToEntry),
|
||||
R.FromEntries[string, ProviderFactory],
|
||||
)
|
||||
|
||||
// assembleProviders constructs the provider map for item and non-item providers
|
||||
assembleProviders = F.Flow3(
|
||||
A.Partition(isItemProvider),
|
||||
T.Map2(collectProviders, collectItemProviders),
|
||||
T.Tupled2(mergeProviders.Concat),
|
||||
)
|
||||
)
|
||||
|
||||
var emptyMulti any = A.Empty[any]()
|
||||
|
||||
var emptyMultiDependency = F.Constant1[Dependency](F.Constant1[InjectableFactory](IOE.Of[error](emptyMulti)))
|
||||
|
||||
func logEntryExit(name string, token Dependency) func() {
|
||||
log.Printf("Entry: [%s] -> [%s]:[%s]", name, token.Id(), token.String())
|
||||
return func() {
|
||||
log.Printf("Exit: [%s] -> [%s]:[%s]", name, token.Id(), token.String())
|
||||
}
|
||||
}
|
||||
|
||||
// isMultiDependency tests if a dependency is a container dependency
|
||||
func isMultiDependency(dep Dependency) bool {
|
||||
return dep.Type() == Multi
|
||||
return dep.Flag()&Multi == Multi
|
||||
}
|
||||
|
||||
var handleMissingProvider = F.Flow2(
|
||||
F.Ternary(isMultiDependency, emptyMultiDependency, missingProviderError),
|
||||
F.Constant[ProviderFactory],
|
||||
)
|
||||
|
||||
// isItemProvider tests if a provivder provides a single item
|
||||
func isItemProvider(provider Provider) bool {
|
||||
return provider.Provides().Type() == Item
|
||||
return provider.Provides().Flag()&Item == Item
|
||||
}
|
||||
|
||||
// itemProviderFactory combines multiple factories into one, returning an array
|
||||
@@ -85,29 +107,7 @@ func itemProviderFactory(fcts []ProviderFactory) ProviderFactory {
|
||||
}
|
||||
}
|
||||
|
||||
var mergeItemProviders = R.UnionMonoid[string](A.Semigroup[ProviderFactory]())
|
||||
|
||||
// collectItemProviders create a provider map for item providers
|
||||
var collectItemProviders = F.Flow2(
|
||||
A.FoldMap[Provider](mergeItemProviders)(itemProviderToMap),
|
||||
R.Map[string](itemProviderFactory),
|
||||
)
|
||||
|
||||
// collectProviders collects non-item providers
|
||||
var collectProviders = F.Flow2(
|
||||
A.Map(providerToEntry),
|
||||
R.FromEntries[string, ProviderFactory],
|
||||
)
|
||||
|
||||
var mergeProviders = R.UnionLastMonoid[string, ProviderFactory]()
|
||||
|
||||
// assembleProviders constructs the provider map for item and non-item providers
|
||||
var assembleProviders = F.Flow3(
|
||||
A.Partition(isItemProvider),
|
||||
T.Map2(collectProviders, collectItemProviders),
|
||||
T.Tupled2(mergeProviders.Concat),
|
||||
)
|
||||
|
||||
// MakeInjector creates an [InjectableFactory] based on a set of [Provider]s
|
||||
func MakeInjector(providers []Provider) InjectableFactory {
|
||||
|
||||
type Result = IOE.IOEither[error, any]
|
||||
@@ -126,8 +126,6 @@ func MakeInjector(providers []Provider) InjectableFactory {
|
||||
// lazy initialization, so we can cross reference it
|
||||
injFct = func(token Dependency) Result {
|
||||
|
||||
defer logEntryExit("inj", token)()
|
||||
|
||||
key := token.Id()
|
||||
|
||||
// according to https://github.com/golang/go/issues/44159 this
|
||||
@@ -135,8 +133,7 @@ func MakeInjector(providers []Provider) InjectableFactory {
|
||||
actual, loaded := resolved.Load(key)
|
||||
if !loaded {
|
||||
|
||||
computeResult := func() Result {
|
||||
defer logEntryExit("computeResult", token)()
|
||||
computeResult := L.MakeLazy(func() Result {
|
||||
return F.Pipe5(
|
||||
token,
|
||||
T.Replicate2[Dependency],
|
||||
@@ -149,7 +146,7 @@ func MakeInjector(providers []Provider) InjectableFactory {
|
||||
IG.Ap[ProviderFactory](injFct),
|
||||
IOE.Memoize[error, any],
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
actual, _ = resolved.LoadOrStore(key, F.Pipe1(
|
||||
computeResult,
|
||||
|
@@ -21,6 +21,7 @@ import (
|
||||
A "github.com/IBM/fp-go/array"
|
||||
E "github.com/IBM/fp-go/either"
|
||||
F "github.com/IBM/fp-go/function"
|
||||
I "github.com/IBM/fp-go/identity"
|
||||
IO "github.com/IBM/fp-go/io"
|
||||
IOG "github.com/IBM/fp-go/io/generic"
|
||||
IOE "github.com/IBM/fp-go/ioeither"
|
||||
@@ -34,10 +35,14 @@ type InjectableFactory = func(Dependency) IOE.IOEither[error, any]
|
||||
type ProviderFactory = func(InjectableFactory) IOE.IOEither[error, any]
|
||||
|
||||
type paramIndex = map[int]int
|
||||
type paramValue = map[int]any
|
||||
type handler = func(paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue]
|
||||
|
||||
type Provider interface {
|
||||
fmt.Stringer
|
||||
// Provides returns the [Dependency] implemented by this provider
|
||||
Provides() Dependency
|
||||
// Factory returns s function that can create an instance of the dependency based on an [InjectableFactory]
|
||||
Factory() ProviderFactory
|
||||
}
|
||||
|
||||
@@ -62,19 +67,67 @@ func MakeProvider(token Dependency, fct ProviderFactory) Provider {
|
||||
return &provider{token, fct}
|
||||
}
|
||||
|
||||
func mapFromToken(idx int, token Dependency) map[TokenType]paramIndex {
|
||||
return R.Singleton(token.Type(), R.Singleton(idx, idx))
|
||||
func mapFromToken(idx int, token Dependency) map[int]paramIndex {
|
||||
return R.Singleton(token.Flag()&BehaviourMask, R.Singleton(idx, idx))
|
||||
}
|
||||
|
||||
var mergeTokenMaps = R.UnionMonoid[TokenType](R.UnionLastSemigroup[int, int]())
|
||||
var foldDeps = A.FoldMapWithIndex[Dependency](mergeTokenMaps)(mapFromToken)
|
||||
var (
|
||||
mergeTokenMaps = R.UnionMonoid[int](R.UnionLastSemigroup[int, int]())
|
||||
foldDeps = A.FoldMapWithIndex[Dependency](mergeTokenMaps)(mapFromToken)
|
||||
mergeMaps = R.UnionLastMonoid[int, any]()
|
||||
collectParams = R.CollectOrd[any, any](Int.Ord)(F.SK[int, any])
|
||||
|
||||
var lookupIdentity = R.Lookup[paramIndex](Identity)
|
||||
var lookupOption = R.Lookup[paramIndex](Option)
|
||||
var lookupIOEither = R.Lookup[paramIndex](IOEither)
|
||||
var lookupIOOption = R.Lookup[paramIndex](IOOption)
|
||||
handlers = map[int]handler{
|
||||
Identity: func(mp paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||
return func(res []IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||
return F.Pipe1(
|
||||
mp,
|
||||
IOE.TraverseRecord[int](getAt(res)),
|
||||
)
|
||||
}
|
||||
},
|
||||
Option: func(mp paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||
return func(res []IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||
return F.Pipe3(
|
||||
mp,
|
||||
IOG.TraverseRecord[IO.IO[map[int]E.Either[error, any]], paramIndex](getAt(res)),
|
||||
IO.Map(R.Map[int](F.Flow2(
|
||||
E.ToOption[error, any],
|
||||
F.ToAny[O.Option[any]],
|
||||
))),
|
||||
IOE.FromIO[error, paramValue],
|
||||
)
|
||||
}
|
||||
},
|
||||
IOEither: func(mp paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||
return func(res []IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||
return F.Pipe2(
|
||||
mp,
|
||||
R.Map[int](F.Flow2(
|
||||
getAt(res),
|
||||
F.ToAny[IOE.IOEither[error, any]],
|
||||
)),
|
||||
IOE.Of[error, paramValue],
|
||||
)
|
||||
}
|
||||
},
|
||||
IOOption: func(mp paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||
return func(res []IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||
return F.Pipe2(
|
||||
mp,
|
||||
R.Map[int](F.Flow3(
|
||||
getAt(res),
|
||||
IOO.FromIOEither[error, any],
|
||||
F.ToAny[IOO.IOOption[any]],
|
||||
)),
|
||||
IOE.Of[error, paramValue],
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type Mapping = map[TokenType]paramIndex
|
||||
type Mapping = map[int]paramIndex
|
||||
|
||||
func getAt[T any](ar []T) func(idx int) T {
|
||||
return func(idx int) T {
|
||||
@@ -82,158 +135,41 @@ func getAt[T any](ar []T) func(idx int) T {
|
||||
}
|
||||
}
|
||||
|
||||
type identityResult = IOE.IOEither[error, map[int]any]
|
||||
|
||||
func handleIdentity(mp Mapping) func(res []IOE.IOEither[error, any]) identityResult {
|
||||
|
||||
onNone := F.Nullary2(R.Empty[int, any], IOE.Of[error, map[int]any])
|
||||
|
||||
return func(res []IOE.IOEither[error, any]) identityResult {
|
||||
return F.Pipe2(
|
||||
mp,
|
||||
lookupIdentity,
|
||||
O.Fold(
|
||||
onNone,
|
||||
IOE.TraverseRecord[int](getAt(res)),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type optionResult = IO.IO[map[int]O.Option[any]]
|
||||
|
||||
func handleOption(mp Mapping) func(res []IOE.IOEither[error, any]) optionResult {
|
||||
|
||||
onNone := F.Nullary2(R.Empty[int, O.Option[any]], IO.Of[map[int]O.Option[any]])
|
||||
|
||||
return func(res []IOE.IOEither[error, any]) optionResult {
|
||||
|
||||
return F.Pipe2(
|
||||
mp,
|
||||
lookupOption,
|
||||
O.Fold(
|
||||
onNone,
|
||||
F.Flow2(
|
||||
IOG.TraverseRecord[IO.IO[map[int]E.Either[error, any]], paramIndex](getAt(res)),
|
||||
IO.Map(R.Map[int](E.ToOption[error, any])),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type ioeitherResult = IO.IO[map[int]IOE.IOEither[error, any]]
|
||||
|
||||
func handleIOEither(mp Mapping) func(res []IOE.IOEither[error, any]) ioeitherResult {
|
||||
|
||||
onNone := F.Nullary2(R.Empty[int, IOE.IOEither[error, any]], IO.Of[map[int]IOE.IOEither[error, any]])
|
||||
|
||||
return func(res []IOE.IOEither[error, any]) ioeitherResult {
|
||||
|
||||
return F.Pipe2(
|
||||
mp,
|
||||
lookupIOEither,
|
||||
O.Fold(
|
||||
onNone,
|
||||
F.Flow2(
|
||||
R.Map[int](getAt(res)),
|
||||
IO.Of[map[int]IOE.IOEither[error, any]],
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type iooptionResult = IO.IO[map[int]IOO.IOOption[any]]
|
||||
|
||||
func handleIOOption(mp Mapping) func(res []IOE.IOEither[error, any]) iooptionResult {
|
||||
|
||||
onNone := F.Nullary2(R.Empty[int, IOO.IOOption[any]], IO.Of[map[int]IOO.IOOption[any]])
|
||||
|
||||
return func(res []IOE.IOEither[error, any]) iooptionResult {
|
||||
|
||||
return F.Pipe2(
|
||||
mp,
|
||||
lookupIOOption,
|
||||
O.Fold(
|
||||
onNone,
|
||||
F.Flow2(
|
||||
R.Map[int](F.Flow2(
|
||||
getAt(res),
|
||||
IOO.FromIOEither[error, any],
|
||||
)),
|
||||
IO.Of[map[int]IOO.IOOption[any]],
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
var optionMapToAny = R.Map[int](F.ToAny[O.Option[any]])
|
||||
var ioeitherMapToAny = R.Map[int](F.ToAny[IOE.IOEither[error, any]])
|
||||
var iooptionMapToAny = R.Map[int](F.ToAny[IOO.IOOption[any]])
|
||||
var mergeMaps = R.UnionLastMonoid[int, any]()
|
||||
var collectParams = R.CollectOrd[any, any](Int.Ord)(F.SK[int, any])
|
||||
|
||||
func mergeArguments(
|
||||
identity identityResult,
|
||||
option optionResult,
|
||||
ioeither ioeitherResult,
|
||||
iooption iooptionResult,
|
||||
) IOE.IOEither[error, []any] {
|
||||
|
||||
return F.Pipe2(
|
||||
A.From(
|
||||
identity,
|
||||
F.Pipe2(
|
||||
option,
|
||||
IO.Map(optionMapToAny),
|
||||
IOE.FromIO[error, map[int]any],
|
||||
),
|
||||
F.Pipe2(
|
||||
ioeither,
|
||||
IO.Map(ioeitherMapToAny),
|
||||
IOE.FromIO[error, map[int]any],
|
||||
),
|
||||
F.Pipe2(
|
||||
iooption,
|
||||
IO.Map(iooptionMapToAny),
|
||||
IOE.FromIO[error, map[int]any],
|
||||
),
|
||||
),
|
||||
IOE.SequenceArray[error, map[int]any],
|
||||
IOE.Map[error](F.Flow2(
|
||||
A.Fold(mergeMaps),
|
||||
collectParams,
|
||||
)),
|
||||
func handleMapping(mp Mapping) func(res []IOE.IOEither[error, any]) IOE.IOEither[error, []any] {
|
||||
preFct := F.Pipe2(
|
||||
mp,
|
||||
R.MapWithIndex(func(idx int, p paramIndex) func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue] {
|
||||
return handlers[idx](p)
|
||||
}),
|
||||
R.Collect[int](F.SK[int, func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue]]),
|
||||
)
|
||||
doFct := F.Flow2(
|
||||
I.Flap[IOE.IOEither[error, paramValue], []IOE.IOEither[error, any]],
|
||||
IOE.TraverseArray[error, func([]IOE.IOEither[error, any]) IOE.IOEither[error, paramValue], paramValue],
|
||||
)
|
||||
postFct := IOE.Map[error](F.Flow2(
|
||||
A.Fold(mergeMaps),
|
||||
collectParams,
|
||||
))
|
||||
|
||||
return func(res []IOE.IOEither[error, any]) IOE.IOEither[error, []any] {
|
||||
return F.Pipe2(
|
||||
preFct,
|
||||
doFct(res),
|
||||
postFct,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MakeProviderFactory constructs a [ProviderFactory] based on a set of [Dependency]s and
|
||||
// a function that accepts the resolved dependencies to return a result
|
||||
func MakeProviderFactory(
|
||||
deps []Dependency,
|
||||
fct func(param ...any) IOE.IOEither[error, any]) ProviderFactory {
|
||||
|
||||
mapping := foldDeps(deps)
|
||||
|
||||
identity := handleIdentity(mapping)
|
||||
optional := handleOption(mapping)
|
||||
ioeither := handleIOEither(mapping)
|
||||
iooption := handleIOOption(mapping)
|
||||
|
||||
f := F.Unvariadic0(fct)
|
||||
|
||||
return func(inj InjectableFactory) IOE.IOEither[error, any] {
|
||||
// resolve all dependencies
|
||||
resolved := A.MonadMap(deps, inj)
|
||||
// resolve dependencies
|
||||
return F.Pipe1(
|
||||
mergeArguments(
|
||||
identity(resolved),
|
||||
optional(resolved),
|
||||
ioeither(resolved),
|
||||
iooption(resolved),
|
||||
),
|
||||
IOE.Chain(f),
|
||||
)
|
||||
}
|
||||
return F.Flow3(
|
||||
F.Curry2(A.MonadMap[Dependency, IOE.IOEither[error, any]])(deps),
|
||||
handleMapping(foldDeps(deps)),
|
||||
IOE.Chain(F.Unvariadic0(fct)),
|
||||
)
|
||||
}
|
||||
|
@@ -17,17 +17,16 @@ package erasure
|
||||
|
||||
import "fmt"
|
||||
|
||||
type TokenType int
|
||||
|
||||
const (
|
||||
Identity TokenType = iota // required dependency
|
||||
Option // optional dependency
|
||||
IOEither // lazy and required
|
||||
IOOption // lazy and optional
|
||||
Multi // array of implementations
|
||||
Item // item of a multi token
|
||||
IOMulti // lazy and multi
|
||||
Unknown
|
||||
BehaviourMask = 0x0f
|
||||
Identity = 0 // required dependency
|
||||
Option = 1 // optional dependency
|
||||
IOEither = 2 // lazy and required
|
||||
IOOption = 3 // lazy and optional
|
||||
|
||||
TypeMask = 0xf0
|
||||
Multi = 1 << 4 // array of implementations
|
||||
Item = 2 << 4 // item of a multi token
|
||||
)
|
||||
|
||||
// Dependency describes the relationship to a service
|
||||
@@ -35,8 +34,8 @@ type Dependency interface {
|
||||
fmt.Stringer
|
||||
// Id returns a unique identifier for a token that can be used as a cache key
|
||||
Id() string
|
||||
// Type returns a tag that identifies the behaviour of the dependency
|
||||
Type() TokenType
|
||||
// Flag returns a tag that identifies the behaviour of the dependency
|
||||
Flag() int
|
||||
}
|
||||
|
||||
func AsDependency[T Dependency](t T) Dependency {
|
||||
|
@@ -276,3 +276,29 @@ func TestEmptyItemProvider(t *testing.T) {
|
||||
|
||||
assert.Equal(t, E.Of[error](A.Empty[string]()), value)
|
||||
}
|
||||
|
||||
func TestDependencyOnMultiProvider(t *testing.T) {
|
||||
// define a multi token
|
||||
injMulti := MakeMultiToken[string]("configs")
|
||||
|
||||
// provide some values
|
||||
v1 := ConstProvider(injMulti.Item(), "Value1")
|
||||
v2 := ConstProvider(injMulti.Item(), "Value2")
|
||||
// mix in non-multi values
|
||||
p1 := ConstProvider(INJ_KEY1, "Value3")
|
||||
p2 := ConstProvider(INJ_KEY2, "Value4")
|
||||
|
||||
fromMulti := func(val string, multi []string) IOE.IOEither[error, string] {
|
||||
return IOE.Of[error](fmt.Sprintf("Val: %s, Multi: %s", val, multi))
|
||||
}
|
||||
p3 := MakeProvider2(INJ_KEY3, INJ_KEY1.Identity(), injMulti.Container().Identity(), fromMulti)
|
||||
|
||||
// populate the injector
|
||||
inj := DIE.MakeInjector(A.From(p1, p2, v1, v2, p3))
|
||||
|
||||
r3 := Resolve(INJ_KEY3)
|
||||
|
||||
v := r3(inj)()
|
||||
|
||||
assert.Equal(t, E.Of[error]("Val: Value3, Multi: [Value1 Value2]"), v)
|
||||
}
|
||||
|
24
di/token.go
24
di/token.go
@@ -77,7 +77,7 @@ var genId = makeId()
|
||||
type token[T any] struct {
|
||||
name string
|
||||
id string
|
||||
typ DIE.TokenType
|
||||
flag int
|
||||
toType func(val any) E.Either[error, T]
|
||||
}
|
||||
|
||||
@@ -85,8 +85,8 @@ func (t *token[T]) Id() string {
|
||||
return t.id
|
||||
}
|
||||
|
||||
func (t *token[T]) Type() DIE.TokenType {
|
||||
return t.typ
|
||||
func (t *token[T]) Flag() int {
|
||||
return t.flag
|
||||
}
|
||||
|
||||
func (t *token[T]) String() string {
|
||||
@@ -97,7 +97,7 @@ func (t *token[T]) Unerase(val any) E.Either[error, T] {
|
||||
return t.toType(val)
|
||||
}
|
||||
|
||||
func makeToken[T any](name string, id string, typ DIE.TokenType, unerase func(val any) E.Either[error, T]) Dependency[T] {
|
||||
func makeToken[T any](name string, id string, typ int, unerase func(val any) E.Either[error, T]) Dependency[T] {
|
||||
return &token[T]{name, id, typ, unerase}
|
||||
}
|
||||
|
||||
@@ -157,17 +157,17 @@ func MakeMultiToken[T any](name string) MultiInjectionToken[T] {
|
||||
itemName := fmt.Sprintf("Item[%s]", name)
|
||||
// container
|
||||
container := &injectionToken[[]T]{
|
||||
token[[]T]{containerName, id, DIE.Multi, toContainer},
|
||||
makeToken[O.Option[[]T]](fmt.Sprintf("Option[%s]", containerName), id, DIE.Unknown, toOptionType(toContainer)),
|
||||
makeToken[IOE.IOEither[error, []T]](fmt.Sprintf("IOEither[%s]", containerName), id, DIE.IOMulti, toIOEitherType(toContainer)),
|
||||
makeToken[IOO.IOOption[[]T]](fmt.Sprintf("IOOption[%s]", containerName), id, DIE.Unknown, toIOOptionType(toContainer)),
|
||||
token[[]T]{containerName, id, DIE.Multi | DIE.Identity, toContainer},
|
||||
makeToken[O.Option[[]T]](fmt.Sprintf("Option[%s]", containerName), id, DIE.Multi|DIE.Option, toOptionType(toContainer)),
|
||||
makeToken[IOE.IOEither[error, []T]](fmt.Sprintf("IOEither[%s]", containerName), id, DIE.Multi|DIE.IOEither, toIOEitherType(toContainer)),
|
||||
makeToken[IOO.IOOption[[]T]](fmt.Sprintf("IOOption[%s]", containerName), id, DIE.Multi|DIE.IOOption, toIOOptionType(toContainer)),
|
||||
}
|
||||
// item
|
||||
item := &injectionToken[T]{
|
||||
token[T]{itemName, id, DIE.Item, toItem},
|
||||
makeToken[O.Option[T]](fmt.Sprintf("Option[%s]", itemName), id, DIE.Unknown, toOptionType(toItem)),
|
||||
makeToken[IOE.IOEither[error, T]](fmt.Sprintf("IOEither[%s]", itemName), id, DIE.Unknown, toIOEitherType(toItem)),
|
||||
makeToken[IOO.IOOption[T]](fmt.Sprintf("IOOption[%s]", itemName), id, DIE.Unknown, toIOOptionType(toItem)),
|
||||
token[T]{itemName, id, DIE.Item | DIE.Identity, toItem},
|
||||
makeToken[O.Option[T]](fmt.Sprintf("Option[%s]", itemName), id, DIE.Item|DIE.Option, toOptionType(toItem)),
|
||||
makeToken[IOE.IOEither[error, T]](fmt.Sprintf("IOEither[%s]", itemName), id, DIE.Item|DIE.IOEither, toIOEitherType(toItem)),
|
||||
makeToken[IOO.IOOption[T]](fmt.Sprintf("IOOption[%s]", itemName), id, DIE.Item|DIE.IOOption, toIOOptionType(toItem)),
|
||||
}
|
||||
// returns the token
|
||||
return &multiInjectionToken[T]{container, item}
|
||||
|
Reference in New Issue
Block a user