diff --git a/builder.go b/builder.go index f0c2406..e4aebc7 100644 --- a/builder.go +++ b/builder.go @@ -198,6 +198,20 @@ func AddSingleton[T any](cb ContainerBuilder, ctor any, implementedInterfaceType cb.Add(Singleton[T](ctor, implementedInterfaceTypes...)) } +// AddFunc is a convenience method to add a singleton service descriptor to the ContainerBuilder. +func AddFunc[T any](cb ContainerBuilder, ctor any) { + AddSingleton[T](cb, ctor) +} + +// AddFuncByLookupKey is a convenience method to add a singleton service descriptor to the ContainerBuilder. +func AddFuncWithLookupKeys[T any](cb ContainerBuilder, + ctor any, + lookupKeys []string, + metadata map[string]interface{}, +) { + AddSingletonWithLookupKeys[T](cb, ctor, lookupKeys, metadata) +} + // Add a singleton service descriptor to the ContainerBuilder. // T is the service type, // cb is the ContainerBuilder, diff --git a/funcs_test.go b/funcs_test.go new file mode 100644 index 0000000..0ca77e3 --- /dev/null +++ b/funcs_test.go @@ -0,0 +1,47 @@ +package di + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +type ( + MyFunc func() string +) + +func AddMyFunc(b ContainerBuilder) { + AddFunc[MyFunc](b, func() MyFunc { + return func() string { + return "Hello" + } + }) +} +func AddMyFuncByName(b ContainerBuilder, name string) { + AddFuncWithLookupKeys[MyFunc](b, + func() MyFunc { + return func() string { + return "Hello: " + name + } + }, []string{name}, map[string]interface{}{}) +} +func TestAddMyFunc(t *testing.T) { + b := Builder() + // Build the container + AddMyFunc(b) + c := b.Build() + + myFunc := Get[MyFunc](c) + require.NotNil(t, myFunc) + require.Equal(t, "Hello", myFunc()) +} +func TestAddMyFuncByName(t *testing.T) { + b := Builder() + // Build the container + AddMyFuncByName(b, "test") + c := b.Build() + + myFunc := GetByLookupKey[MyFunc](c, "test") + require.NotNil(t, myFunc) + require.Equal(t, "Hello: test", myFunc()) +} diff --git a/lookup_keys_test.go b/lookup_keys_test.go new file mode 100644 index 0000000..2fe1263 --- /dev/null +++ b/lookup_keys_test.go @@ -0,0 +1,148 @@ +package di + +import ( + "fmt" + "reflect" + "testing" + + "github.com/stretchr/testify/require" +) + +func AddSingletonEmployeesWithLookupKeys(b ContainerBuilder) { + AddSingletonWithLookupKeys[*employee](b, + func() *employee { + return &employee{Name: "1"} + }, []string{"1"}, map[string]interface{}{"name": "1"}, + reflect.TypeOf((*IEmployee)(nil))) + AddSingletonWithLookupKeys[*employee](b, + func() *employee { + return &employee{Name: "2a"} + }, []string{"2"}, map[string]interface{}{"name": "2a"}, + reflect.TypeOf((*IEmployee)(nil))) + AddSingletonWithLookupKeys[*employee](b, + func() *employee { + return &employee{Name: "2"} + }, []string{"2"}, map[string]interface{}{"name": "2"}, + reflect.TypeOf((*IEmployee)(nil))) +} +func AddTransientEmployeesWithLookupKeys(b ContainerBuilder) { + AddTransientWithLookupKeys[*employee](b, + func() *employee { + return &employee{Name: "1"} + }, []string{"1"}, + map[string]interface{}{"name": "1"}, + reflect.TypeOf((*IEmployee)(nil))) + AddTransientWithLookupKeys[*employee](b, + func() *employee { + return &employee{Name: "2"} + }, []string{"2"}, + map[string]interface{}{"name": "2"}, + reflect.TypeOf((*IEmployee)(nil))) +} +func AddInstanceEmployeesWithLookupKeys(b ContainerBuilder) { + AddInstanceWithLookupKeys[*employee](b, + &employee{Name: "1"}, []string{"1"}, + map[string]interface{}{"name": "1"}, + reflect.TypeOf((*IEmployee)(nil))) + AddInstanceWithLookupKeys[*employee](b, + &employee{Name: "2"}, []string{"2"}, + map[string]interface{}{"name": "2"}, + reflect.TypeOf((*IEmployee)(nil))) +} +func AddScopedHandlersWithLookupKeys(b ContainerBuilder) { + AddScopedWithLookupKeys[*handler](b, + func() *handler { + return &handler{path: "1"} + }, []string{"1"}, map[string]interface{}{"name": "1"}, + reflect.TypeOf((*IHandler)(nil))) + AddScopedWithLookupKeys[*handler](b, + func() *handler { + return &handler{path: "2"} + }, []string{"2"}, map[string]interface{}{"name": "2"}, + reflect.TypeOf((*IHandler)(nil))) +} + +func TestManyWithScopeWithLookupKeys(t *testing.T) { + b := Builder() + // Build the container + AddScopedHandlersWithLookupKeys(b) + c := b.Build() + scopeFactory := Get[ScopeFactory](c) + scope1 := scopeFactory.CreateScope() + ctn := scope1.Container() + descriptors := ctn.GetDescriptors() + require.Equal(t, 2, len(descriptors)) + for _, d := range descriptors { + require.NotEmpty(t, d.Metadata) + _, ok := d.Metadata["name"] + require.True(t, ok) + _, ok = d.Metadata["name"].(string) + require.True(t, ok) + + fmt.Println(d) + } + handlers := Get[[]IHandler](ctn) + require.Equal(t, 2, len(handlers)) + require.NotPanics(t, func() { + h := GetByLookupKey[IHandler](c, "1") + require.NotNil(t, h) + require.Equal(t, "1", h.GetPath()) + }) +} +func TestManyWithSingletonWithLookupKeys(t *testing.T) { + b := Builder() + // Build the container + AddSingletonEmployeesWithLookupKeys(b) + c := b.Build() + scopeFactory := Get[ScopeFactory](c) + scope1 := scopeFactory.CreateScope() + employees := Get[[]IEmployee](scope1.Container()) + require.Equal(t, 3, len(employees)) + require.NotPanics(t, func() { + h := GetByLookupKey[IEmployee](c, "1") + require.NotNil(t, h) + require.Equal(t, "1", h.GetName()) + }) + require.NotPanics(t, func() { + h := GetByLookupKey[IEmployee](c, "2") + require.NotNil(t, h) + require.Equal(t, "2", h.GetName()) + }) +} +func TestManyWithTransientWithLookupKeys(t *testing.T) { + b := Builder() + // Build the container + AddTransientEmployeesWithLookupKeys(b) + c := b.Build() + scopeFactory := Get[ScopeFactory](c) + scope1 := scopeFactory.CreateScope() + employees := Get[[]IEmployee](scope1.Container()) + require.Equal(t, 2, len(employees)) + require.NotPanics(t, func() { + h := GetByLookupKey[IEmployee](c, "1") + require.NotNil(t, h) + require.Equal(t, "1", h.GetName()) + }) +} +func TestManyWithInstanceWithLookupKeys(t *testing.T) { + b := Builder() + // Build the container + AddInstanceEmployeesWithLookupKeys(b) + c := b.Build() + scopeFactory := Get[ScopeFactory](c) + scope1 := scopeFactory.CreateScope() + employees := Get[[]IEmployee](scope1.Container()) + require.Equal(t, 2, len(employees)) + require.NotPanics(t, func() { + h := GetByLookupKey[IEmployee](c, "1") + require.NotNil(t, h) + require.Equal(t, "1", h.GetName()) + }) + employeePtrs := Get[[]*employee](scope1.Container()) + require.Equal(t, 2, len(employeePtrs)) + require.NotPanics(t, func() { + h := GetByLookupKey[*employee](c, "1") + require.NotNil(t, h) + require.Equal(t, "1", h.GetName()) + }) +} diff --git a/many_interfaces_test.go b/many_interfaces_test.go index 3d006d9..65a48b4 100644 --- a/many_interfaces_test.go +++ b/many_interfaces_test.go @@ -80,59 +80,6 @@ func AddSingletonTime(b ContainerBuilder) { return &myTime{} }) } -func AddSingletonEmployeesWithLookupKeys(b ContainerBuilder) { - AddSingletonWithLookupKeys[*employee](b, - func() *employee { - return &employee{Name: "1"} - }, []string{"1"}, map[string]interface{}{"name": "1"}, - reflect.TypeOf((*IEmployee)(nil))) - AddSingletonWithLookupKeys[*employee](b, - func() *employee { - return &employee{Name: "2a"} - }, []string{"2"}, map[string]interface{}{"name": "2a"}, - reflect.TypeOf((*IEmployee)(nil))) - AddSingletonWithLookupKeys[*employee](b, - func() *employee { - return &employee{Name: "2"} - }, []string{"2"}, map[string]interface{}{"name": "2"}, - reflect.TypeOf((*IEmployee)(nil))) -} -func AddTransientEmployeesWithLookupKeys(b ContainerBuilder) { - AddTransientWithLookupKeys[*employee](b, - func() *employee { - return &employee{Name: "1"} - }, []string{"1"}, - map[string]interface{}{"name": "1"}, - reflect.TypeOf((*IEmployee)(nil))) - AddTransientWithLookupKeys[*employee](b, - func() *employee { - return &employee{Name: "2"} - }, []string{"2"}, - map[string]interface{}{"name": "2"}, - reflect.TypeOf((*IEmployee)(nil))) -} -func AddInstanceEmployeesWithLookupKeys(b ContainerBuilder) { - AddInstanceWithLookupKeys[*employee](b, - &employee{Name: "1"}, []string{"1"}, - map[string]interface{}{"name": "1"}, - reflect.TypeOf((*IEmployee)(nil))) - AddInstanceWithLookupKeys[*employee](b, - &employee{Name: "2"}, []string{"2"}, - map[string]interface{}{"name": "2"}, - reflect.TypeOf((*IEmployee)(nil))) -} -func AddScopedHandlersWithLookupKeys(b ContainerBuilder) { - AddScopedWithLookupKeys[*handler](b, - func() *handler { - return &handler{path: "1"} - }, []string{"1"}, map[string]interface{}{"name": "1"}, - reflect.TypeOf((*IHandler)(nil))) - AddScopedWithLookupKeys[*handler](b, - func() *handler { - return &handler{path: "2"} - }, []string{"2"}, map[string]interface{}{"name": "2"}, - reflect.TypeOf((*IHandler)(nil))) -} func AddSingletonDepartments(b ContainerBuilder, names ...string) { // pointer to interface type @@ -313,91 +260,7 @@ func TestSingleton(t *testing.T) { require.Equal(t, "IT", company.GetDepartment().GetName()) require.Equal(t, "Contoso", company.GetName()) } -func TestManyWithScopeWithLookupKeys(t *testing.T) { - b := Builder() - // Build the container - AddScopedHandlersWithLookupKeys(b) - c := b.Build() - scopeFactory := Get[ScopeFactory](c) - scope1 := scopeFactory.CreateScope() - ctn := scope1.Container() - descriptors := ctn.GetDescriptors() - require.Equal(t, 2, len(descriptors)) - for _, d := range descriptors { - require.NotEmpty(t, d.Metadata) - _, ok := d.Metadata["name"] - require.True(t, ok) - _, ok = d.Metadata["name"].(string) - require.True(t, ok) - - fmt.Println(d) - } - handlers := Get[[]IHandler](ctn) - require.Equal(t, 2, len(handlers)) - require.NotPanics(t, func() { - h := GetByLookupKey[IHandler](c, "1") - require.NotNil(t, h) - require.Equal(t, "1", h.GetPath()) - }) -} -func TestManyWithSingletonWithLookupKeys(t *testing.T) { - b := Builder() - // Build the container - AddSingletonEmployeesWithLookupKeys(b) - c := b.Build() - scopeFactory := Get[ScopeFactory](c) - scope1 := scopeFactory.CreateScope() - employees := Get[[]IEmployee](scope1.Container()) - require.Equal(t, 3, len(employees)) - require.NotPanics(t, func() { - h := GetByLookupKey[IEmployee](c, "1") - require.NotNil(t, h) - require.Equal(t, "1", h.GetName()) - }) - require.NotPanics(t, func() { - h := GetByLookupKey[IEmployee](c, "2") - require.NotNil(t, h) - require.Equal(t, "2", h.GetName()) - }) -} -func TestManyWithTransientWithLookupKeys(t *testing.T) { - b := Builder() - // Build the container - AddTransientEmployeesWithLookupKeys(b) - c := b.Build() - scopeFactory := Get[ScopeFactory](c) - scope1 := scopeFactory.CreateScope() - employees := Get[[]IEmployee](scope1.Container()) - require.Equal(t, 2, len(employees)) - require.NotPanics(t, func() { - h := GetByLookupKey[IEmployee](c, "1") - require.NotNil(t, h) - require.Equal(t, "1", h.GetName()) - }) -} -func TestManyWithInstanceWithLookupKeys(t *testing.T) { - b := Builder() - // Build the container - AddInstanceEmployeesWithLookupKeys(b) - c := b.Build() - scopeFactory := Get[ScopeFactory](c) - scope1 := scopeFactory.CreateScope() - employees := Get[[]IEmployee](scope1.Container()) - require.Equal(t, 2, len(employees)) - require.NotPanics(t, func() { - h := GetByLookupKey[IEmployee](c, "1") - require.NotNil(t, h) - require.Equal(t, "1", h.GetName()) - }) - employeePtrs := Get[[]*employee](scope1.Container()) - require.Equal(t, 2, len(employeePtrs)) - require.NotPanics(t, func() { - h := GetByLookupKey[*employee](c, "1") - require.NotNil(t, h) - require.Equal(t, "1", h.GetName()) - }) -} func TestManyWithScope(t *testing.T) { b := Builder() AddSingletonTime(b)