parent
34d8a15f06
commit
bb44a78885
@ -1,27 +0,0 @@ |
||||
package repositories |
||||
|
||||
import ( |
||||
"sorbet/pkg/ioc" |
||||
) |
||||
|
||||
func Init() { |
||||
ioc.MustFactory(NewCompanyRepository) |
||||
ioc.MustFactory(NewCompanyDepartmentRepository) |
||||
ioc.MustFactory(NewCompanyStaffRepository) |
||||
ioc.MustFactory(NewConfigRepository) |
||||
ioc.MustFactory(NewConfigGroupRepository) |
||||
ioc.MustFactory(NewFeatureRepository) |
||||
ioc.MustFactory(NewFeatureCategoryRepository) |
||||
ioc.MustFactory(NewFeatureConfigRepository) |
||||
ioc.MustFactory(NewFeatureContentRepository) |
||||
ioc.MustFactory(NewFeatureContentChapterRepository) |
||||
ioc.MustFactory(NewFeatureContentDetailRepository) |
||||
ioc.MustFactory(NewResourceRepository) |
||||
ioc.MustFactory(NewResourceCategoryRepository) |
||||
ioc.MustFactory(NewSystemLogRepository) |
||||
ioc.MustFactory(NewSystemMenuRepository) |
||||
ioc.MustFactory(NewSystemPermissionRepository) |
||||
ioc.MustFactory(NewSystemRoleRepository) |
||||
ioc.MustFactory(NewSystemRolePowerRepository) |
||||
ioc.MustFactory(NewSystemUserRepository) |
||||
} |
@ -1,228 +0,0 @@ |
||||
package ioc |
||||
|
||||
import ( |
||||
"errors" |
||||
"fmt" |
||||
"reflect" |
||||
) |
||||
|
||||
type binding struct { |
||||
name string |
||||
typ reflect.Type |
||||
resolver any |
||||
shared bool |
||||
} |
||||
|
||||
func (b *binding) make(c *Container) (reflect.Value, error) { |
||||
if v, exists := c.instances[b.typ][b.name]; exists { |
||||
return v, nil |
||||
} |
||||
val, err := c.Invoke(b.resolver) |
||||
if err != nil { |
||||
return reflect.Value{}, err |
||||
} |
||||
rv := val[0] |
||||
if len(val) == 2 { |
||||
err = val[1].Interface().(error) |
||||
if err != nil { |
||||
return reflect.Value{}, err |
||||
} |
||||
} |
||||
if b.shared { |
||||
if _, exists := c.instances[b.typ]; !exists { |
||||
c.instances[b.typ] = make(map[string]reflect.Value) |
||||
} |
||||
c.instances[b.typ][b.name] = rv |
||||
} |
||||
return rv, nil |
||||
} |
||||
|
||||
func (b *binding) mustMake(c *Container) reflect.Value { |
||||
val, err := b.make(c) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
return val |
||||
} |
||||
|
||||
type Container struct { |
||||
// 注册的工厂函数
|
||||
factories map[reflect.Type]map[string]*binding |
||||
// 注册的共享实例
|
||||
instances map[reflect.Type]map[string]reflect.Value |
||||
parent *Container |
||||
} |
||||
|
||||
func New() *Container { |
||||
return &Container{ |
||||
factories: make(map[reflect.Type]map[string]*binding), |
||||
instances: make(map[reflect.Type]map[string]reflect.Value), |
||||
parent: nil, |
||||
} |
||||
} |
||||
|
||||
// Fork 分支
|
||||
func (c *Container) Fork() *Container { |
||||
ioc := New() |
||||
ioc.parent = c |
||||
return ioc |
||||
} |
||||
|
||||
// Bind 绑定值到容器,有效类型:
|
||||
// - 接口的具体实现值
|
||||
// - 结构体的实例
|
||||
// - 类型的值(尽量不要使用原始类型,而应该使用元素类型的变体)
|
||||
func (c *Container) Bind(instance any) { |
||||
c.NamedBind("", instance) |
||||
} |
||||
|
||||
// NamedBind 绑定具名值到容器
|
||||
func (c *Container) NamedBind(name string, instance any) { |
||||
//typ := InterfaceOf(instance)
|
||||
typ := reflect.TypeOf(instance) |
||||
if _, ok := c.instances[typ]; !ok { |
||||
c.instances[typ] = make(map[string]reflect.Value) |
||||
} |
||||
c.instances[typ][name] = reflect.ValueOf(instance) |
||||
} |
||||
|
||||
// Factory 绑定工厂函数
|
||||
func (c *Container) Factory(factory any, shared ...bool) error { |
||||
return c.NamedFactory("", factory, shared...) |
||||
} |
||||
|
||||
// NamedFactory 绑定具名工厂函数
|
||||
func (c *Container) NamedFactory(name string, factory any, shared ...bool) error { |
||||
reflectedFactory := reflect.TypeOf(factory) |
||||
if reflectedFactory.Kind() != reflect.Func { |
||||
return errors.New("container: the factory must be a function") |
||||
} |
||||
if returnCount := reflectedFactory.NumOut(); returnCount == 0 || returnCount > 2 { |
||||
return errors.New("container: factory function signature is invalid - it must return abstract, or abstract and error") |
||||
} |
||||
// TODO(hupeh): 验证第二个参数必须是 error 接口
|
||||
concreteType := reflectedFactory.Out(0) |
||||
for i := 0; i < reflectedFactory.NumIn(); i++ { |
||||
// 循环依赖
|
||||
if reflectedFactory.In(i) == concreteType { |
||||
return fmt.Errorf("container: factory function signature is invalid - depends on abstract it returns") |
||||
} |
||||
} |
||||
if _, exists := c.factories[concreteType]; !exists { |
||||
c.factories[concreteType] = make(map[string]*binding) |
||||
} |
||||
bd := &binding{ |
||||
name: name, |
||||
typ: concreteType, |
||||
resolver: factory, |
||||
shared: false, |
||||
} |
||||
for _, b := range shared { |
||||
bd.shared = b |
||||
} |
||||
c.factories[concreteType][name] = bd |
||||
return nil |
||||
} |
||||
|
||||
// Resolve 完成的注入
|
||||
func (c *Container) Resolve(i any) error { |
||||
v := reflect.ValueOf(i) |
||||
for v.Kind() == reflect.Ptr { |
||||
v = v.Elem() |
||||
} |
||||
if v.Kind() != reflect.Struct { |
||||
return errors.New("must given a struct") |
||||
} |
||||
t := v.Type() |
||||
for i := 0; i < v.NumField(); i++ { |
||||
f := v.Field(i) |
||||
structField := t.Field(i) |
||||
inject, willInject := structField.Tag.Lookup("inject") |
||||
if !f.CanSet() { |
||||
if willInject { |
||||
return fmt.Errorf("container: cannot make %v field", t.Field(i).Name) |
||||
} |
||||
continue |
||||
} |
||||
ft := f.Type() |
||||
fv := c.NamedGet(inject, ft) |
||||
if !fv.IsValid() { |
||||
return fmt.Errorf("value not found for type %v", ft) |
||||
} |
||||
f.Set(fv) |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
// Get 获取指定类型的值
|
||||
func (c *Container) Get(t reflect.Type) reflect.Value { |
||||
return c.NamedGet("", t) |
||||
} |
||||
|
||||
// NamedGet 通过注入的名称获取指定类型的值
|
||||
func (c *Container) NamedGet(name string, t reflect.Type) reflect.Value { |
||||
val, exists := c.instances[t][name] |
||||
|
||||
if exists && val.IsValid() { |
||||
return val |
||||
} |
||||
|
||||
if factory, exists := c.factories[t][name]; exists { |
||||
val = factory.mustMake(c) |
||||
} |
||||
|
||||
if val.IsValid() || t.Kind() != reflect.Interface { |
||||
goto RESULT |
||||
} |
||||
|
||||
// 使用共享值里面该接口的实现者
|
||||
for k, v := range c.instances { |
||||
if k.Implements(t) { |
||||
for _, value := range v { |
||||
if value.IsValid() { |
||||
val = value |
||||
goto RESULT |
||||
} |
||||
} |
||||
break |
||||
} |
||||
} |
||||
|
||||
// 使用工厂函数里面该接口的实现者
|
||||
for k, v := range c.factories { |
||||
if k.Implements(t) { |
||||
for _, bd := range v { |
||||
if x := bd.mustMake(c); x.IsValid() { |
||||
val = x |
||||
goto RESULT |
||||
} |
||||
} |
||||
break |
||||
} |
||||
} |
||||
|
||||
RESULT: |
||||
if !val.IsValid() && c.parent != nil { |
||||
val = c.parent.NamedGet(name, t) |
||||
} |
||||
return val |
||||
} |
||||
|
||||
// Invoke 执行函数
|
||||
func (c *Container) Invoke(f any) ([]reflect.Value, error) { |
||||
t := reflect.TypeOf(f) |
||||
if t.Kind() != reflect.Func { |
||||
return nil, errors.New("container: invalid function") |
||||
} |
||||
|
||||
var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
|
||||
for i := 0; i < t.NumIn(); i++ { |
||||
argType := t.In(i) |
||||
val := c.Get(argType) |
||||
if !val.IsValid() { |
||||
return nil, fmt.Errorf("value not found for type %v", argType) |
||||
} |
||||
in[i] = val |
||||
} |
||||
return reflect.ValueOf(f).Call(in), nil |
||||
} |
@ -1,96 +0,0 @@ |
||||
package ioc |
||||
|
||||
import ( |
||||
"errors" |
||||
"reflect" |
||||
) |
||||
|
||||
var ( |
||||
ErrValueNotFound = errors.New("ioc: value not found") |
||||
) |
||||
|
||||
var global = New() |
||||
|
||||
// Fork 分支
|
||||
func Fork() *Container { |
||||
return global.Fork() |
||||
} |
||||
|
||||
// Bind 绑定值到容器,有效类型:
|
||||
//
|
||||
// - 接口的具体实现值
|
||||
// - 结构体的实例
|
||||
// - 类型的值(尽量不要使用原始类型,而应该使用元素类型的变体)
|
||||
func Bind(instance any) { |
||||
global.Bind(instance) |
||||
} |
||||
|
||||
// NamedBind 绑定具名值到容器
|
||||
func NamedBind(name string, instance any) { |
||||
global.NamedBind(name, instance) |
||||
} |
||||
|
||||
// Factory 绑定工厂函数
|
||||
func Factory(factory any, shared ...bool) error { |
||||
return global.Factory(factory, shared...) |
||||
} |
||||
|
||||
func MustFactory(factory any, shared ...bool) { |
||||
err := Factory(factory, shared...) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
} |
||||
|
||||
// NamedFactory 绑定具名工厂函数
|
||||
func NamedFactory(name string, factory any, shared ...bool) error { |
||||
return global.NamedFactory(name, factory, shared...) |
||||
} |
||||
|
||||
func MustNamedFactory(name string, factory any, shared ...bool) { |
||||
err := NamedFactory(name, factory, shared...) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
} |
||||
|
||||
// Resolve 完成的注入
|
||||
func Resolve(i any) error { |
||||
return global.Resolve(i) |
||||
} |
||||
|
||||
// Get 获取指定类型的值
|
||||
func Get[T any]() (*T, error) { |
||||
return NamedGet[T]("") |
||||
} |
||||
|
||||
func MustGet[T any]() *T { |
||||
return MustNamedGet[T]("") |
||||
} |
||||
|
||||
// NamedGet 通过注入的名称获取指定类型的值
|
||||
func NamedGet[T any](name string) (*T, error) { |
||||
var abs T |
||||
t := reflect.TypeOf(&abs) |
||||
v := global.NamedGet(name, t) |
||||
if !v.IsValid() { |
||||
return nil, ErrValueNotFound |
||||
} |
||||
if x, ok := v.Interface().(*T); ok { |
||||
return x, nil |
||||
} |
||||
return nil, ErrValueNotFound |
||||
} |
||||
|
||||
func MustNamedGet[T any](name string) *T { |
||||
v, err := NamedGet[T](name) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
return v |
||||
} |
||||
|
||||
// Invoke 执行函数
|
||||
func Invoke(f any) ([]reflect.Value, error) { |
||||
return global.Invoke(f) |
||||
} |
@ -1,19 +0,0 @@ |
||||
package ioc |
||||
|
||||
import "reflect" |
||||
|
||||
// InterfaceOf dereferences a pointer to an Interface type.
|
||||
// It panics if value is not a pointer to an interface.
|
||||
func InterfaceOf(value interface{}) reflect.Type { |
||||
t := reflect.TypeOf(value) |
||||
|
||||
for t.Kind() == reflect.Ptr { |
||||
t = t.Elem() |
||||
} |
||||
|
||||
if t.Kind() != reflect.Interface { |
||||
panic("the value is not a pointer to an interface. (*MyInterface)(nil)") |
||||
} |
||||
|
||||
return t |
||||
} |
Loading…
Reference in new issue