package registry import ( "fmt" "log" "reflect" cda "git.loafle.net/commons_go/di/annotation" cdur "git.loafle.net/commons_go/di/util/reflect" ) func init() { registry = newRegistry() } var registry ComponentRegistry type ComponentRegistry interface { RegisterType(t reflect.Type, ca *cda.ComponentAnnotation) error GetInstance(t reflect.Type) (interface{}, error) GetInstanceByName(name string) (interface{}, error) } func newRegistry() ComponentRegistry { r := &defaultComponentRegistry{} r.definitionsByType = make(map[reflect.Type]*TypeDefinition, 0) r.definitionByName = make(map[string]*TypeDefinition, 0) return r } type defaultComponentRegistry struct { definitionsByType map[reflect.Type]*TypeDefinition definitionByName map[string]*TypeDefinition } func RegisterType(t reflect.Type, ca *cda.ComponentAnnotation) error { return registry.RegisterType(t, ca) } func (cr *defaultComponentRegistry) RegisterType(t reflect.Type, ca *cda.ComponentAnnotation) error { if nil == t { return fmt.Errorf("DI: t[reflect.Type] is nil") } if !cdur.IsTypeKind(t, reflect.Struct, true) { return fmt.Errorf("DI: t[reflect.Type] must be specified but is %v", t) } td, err := cr.buildDefinition(t) if nil != err { return err } cr.definitionsByType[td.RealType] = td if nil != ca { if nil != ca.Names && 0 < len(ca.Names) { for _, n := range ca.Names { cr.definitionByName[n] = td } } } return nil } func GetInstance(t reflect.Type) (interface{}, error) { return registry.GetInstance(t) } func (cr *defaultComponentRegistry) GetInstance(t reflect.Type) (interface{}, error) { if nil == t { return nil, fmt.Errorf("DI: t[reflect.Type] is nil") } var err error cd, ok := cr.definitionsByType[t] if !ok { cd, err = cr.buildDefinition(t) if nil != err { return nil, err } } log.Printf("%v", cd) return nil, nil } func GetInstanceByName(name string) (interface{}, error) { return registry.GetInstanceByName(name) } func (cr *defaultComponentRegistry) GetInstanceByName(name string) (interface{}, error) { return nil, nil } func (cr *defaultComponentRegistry) buildDefinition(t reflect.Type) (*TypeDefinition, error) { if nil == t { return nil, fmt.Errorf("DI: t[reflect.Type] is nil") } rt, pkgName, tName := cdur.GetTypeInfo(t) cd := &TypeDefinition{} cd.PkgName = pkgName cd.TypeName = tName cd.Type = t cd.RealType = rt nf := rt.NumField() if 0 < nf { fields := make(map[string]*FieldDefinition) for i := 0; i < nf; i++ { f := rt.Field(i) as, err := cda.ParseAnnotation(f.Tag) if nil != err { return nil, err } if nil != as && 0 < len(as) { fRT, fPkgName, fTName := cdur.GetTypeInfo(f.Type) fd := &FieldDefinition{ PkgName: fPkgName, TypeName: fTName, Type: f.Type, RealType: fRT, Annotations: as, } fields[f.Name] = fd } } if 0 < len(fields) { cd.Fields = fields } } return cd, nil }