From 1b39bf6e8bcd090682a8a753fa7533e14dfc89d4 Mon Sep 17 00:00:00 2001 From: crusader Date: Thu, 23 Aug 2018 17:06:50 +0900 Subject: [PATCH] ing --- registry/definition.go | 135 ------------- registry/registry.go | 411 -------------------------------------- registry/registry_test.go | 68 ------- 3 files changed, 614 deletions(-) delete mode 100644 registry/definition.go delete mode 100644 registry/registry.go delete mode 100644 registry/registry_test.go diff --git a/registry/definition.go b/registry/definition.go deleted file mode 100644 index 0d23d94..0000000 --- a/registry/definition.go +++ /dev/null @@ -1,135 +0,0 @@ -package registry - -import ( - "fmt" - "reflect" - - cda "git.loafle.net/overflow/di-go/annotation" - cur "git.loafle.net/overflow/util-go/reflect" -) - -type TypeDefinition struct { - FullName string - PkgName string - TypeName string - Type reflect.Type - RealType reflect.Type - - TypeAnnotations map[reflect.Type]cda.Annotation - MethodAnnotations map[string]map[reflect.Type]cda.Annotation - Fields []*FieldDefinition -} - -func (td *TypeDefinition) GetTypeAnnotationByType(at reflect.Type, includeEmbedding bool) cda.Annotation { - if nil == td.TypeAnnotations { - return nil - } - - if !includeEmbedding { - return td.TypeAnnotations[at] - } - - for _, v := range td.TypeAnnotations { - if at == reflect.TypeOf(v) { - return v - } - - if includeEmbedding { - if checkAnnotation(reflect.TypeOf(v), at) { - return v - } - } - } - - return nil -} - -func (td *TypeDefinition) GetMethodAnnotationByType(at reflect.Type, methodName string) cda.Annotation { - if nil == td.MethodAnnotations { - return nil - } - - ms, ok := td.MethodAnnotations[methodName] - if !ok { - return nil - } - - return ms[at] -} - -func (td *TypeDefinition) GetMethodAnnotationsByType(at reflect.Type) map[string]cda.Annotation { - if nil == td.MethodAnnotations { - return nil - } - - mas := make(map[string]cda.Annotation) - for k, v := range td.MethodAnnotations { - a, ok := v[at] - if !ok { - continue - } - mas[k] = a - } - - return mas -} - -func checkAnnotation(t reflect.Type, st reflect.Type) bool { - rt, _, _ := cur.GetTypeInfo(t) - if reflect.Struct != rt.Kind() { - return false - } - - for i := 0; i < rt.NumField(); i++ { - f := rt.Field(i) - - if f.Anonymous { - if f.Type == st { - return true - } - if checkAnnotation(f.Type, st) { - return true - } - } - } - - return false -} - -type FieldDefinition struct { - FieldName string - PkgName string - TypeName string - Type reflect.Type - RealType reflect.Type - - Annotations map[reflect.Type]cda.Annotation -} - -func (fd *FieldDefinition) GetAnnotationByType(at reflect.Type, includeEmbedding bool) cda.Annotation { - if nil == fd.Annotations { - return nil - } - - if !includeEmbedding { - return fd.Annotations[at] - } - - for _, v := range fd.Annotations { - if at == reflect.TypeOf(v) { - return v - } - - if includeEmbedding { - if checkAnnotation(reflect.TypeOf(v), at) { - return v - } - } - } - - return nil -} - -func FullName(pkgName, typeName string) string { - return fmt.Sprintf("%s/%s", pkgName, typeName) -} diff --git a/registry/registry.go b/registry/registry.go deleted file mode 100644 index 5416eda..0000000 --- a/registry/registry.go +++ /dev/null @@ -1,411 +0,0 @@ -package registry - -import ( - "fmt" - "log" - "reflect" - "runtime" - "strings" - - cda "git.loafle.net/overflow/di-go/annotation" - cdia "git.loafle.net/overflow/di-go/injection/annotation" - cur "git.loafle.net/overflow/util-go/reflect" -) - -func init() { - registry = newRegistry() -} - -var registry Registry - -type Registry interface { - RegisterType(t reflect.Type) - RegisterResource(name string, resource interface{}) error - - GetInstance(t reflect.Type) (interface{}, error) - GetInstances(ts []reflect.Type) ([]interface{}, error) - GetInstanceByName(name string) (interface{}, error) - GetInstancesByAnnotationType(t reflect.Type) ([]interface{}, error) - - GetTypeAnnotation(instanceType reflect.Type, annotationType reflect.Type) cda.Annotation - GetMethodAnnotation(instanceType reflect.Type, annotationType reflect.Type, methodName string) cda.Annotation - GetMethodAnnotations(instanceType reflect.Type, annotationType reflect.Type) map[string]cda.Annotation -} - -func newRegistry() Registry { - r := &defaultComponentRegistry{} - r.definitionByType = make(map[reflect.Type]*TypeDefinition, 0) - r.definitionByName = make(map[string]*TypeDefinition, 0) - r.instanceByType = make(map[reflect.Type]interface{}, 0) - r.resourceByName = make(map[string]interface{}, 0) - - return r -} - -type defaultComponentRegistry struct { - definitionByType map[reflect.Type]*TypeDefinition - definitionByName map[string]*TypeDefinition - instanceByType map[reflect.Type]interface{} - resourceByName map[string]interface{} -} - -func RegisterType(t reflect.Type) { - pc, _, _, ok := runtime.Caller(1) - details := runtime.FuncForPC(pc) - if ok && details != nil { - log.Printf("called from %s", details.Name()) - } - - registry.RegisterType(t) -} -func (cr *defaultComponentRegistry) RegisterType(t reflect.Type) { - if nil == t { - log.Panicf("DI: t[reflect.Type] is nil") - } - if !cur.IsTypeKind(t, reflect.Struct, true) { - log.Panicf("DI: t[reflect.Type] must be specified but is %v", t) - } - - td, err := cr.buildDefinition(t) - if nil != err { - log.Panicf("DI: %v", err) - } - - if _, ok := cr.definitionByType[td.Type]; ok { - log.Panicf("DI: The type[%s] of Component is exist already", td.FullName) - } - cr.definitionByType[td.Type] = td - - name := td.TypeName - - if a := td.GetTypeAnnotationByType(cdia.ComponentAnnotationType, true); nil != a { - ca := a.(*cdia.ComponentAnnotation) - if "" != strings.Trim(ca.Name, " ") { - name = ca.Name - } - } - - if eTD, ok := cr.definitionByName[name]; ok { - log.Panicf("DI: The name[%s] of Component is exist already type[%s]", name, eTD.FullName) - } - cr.definitionByName[name] = td -} - -func RegisterResource(name string, resource interface{}) error { - return registry.RegisterResource(name, resource) -} -func (cr *defaultComponentRegistry) RegisterResource(name string, resource interface{}) error { - if _, ok := cr.resourceByName[name]; ok { - return fmt.Errorf("DI: Resource[%s] is already exist", name) - } - cr.resourceByName[name] = resource - - return nil -} - -// GetInstance returns instance of type -// t must be pointer of struct -func GetInstance(t reflect.Type) (interface{}, error) { - return registry.GetInstance(t) -} -func (cr *defaultComponentRegistry) GetInstance(t reflect.Type) (instance interface{}, err error) { - if nil == t { - return nil, fmt.Errorf("DI: t[reflect.Type] is nil") - } - - if reflect.Ptr != t.Kind() { - return nil, fmt.Errorf("DI: t[reflect.Type] must be pointer of struct") - } - - if reflect.Struct != t.Elem().Kind() { - return nil, fmt.Errorf("DI: t[reflect.Type] must be pointer of struct") - } - - var ( - td *TypeDefinition - comV interface{} - ok bool - ) - - rt, _, _ := cur.GetTypeInfo(t) - if td, ok = cr.definitionByType[t]; !ok { - if td, err = cr.buildDefinition(t); nil != err { - return nil, fmt.Errorf("DI: %v", err) - } - } - - if comV, ok = cr.instanceByType[td.RealType]; ok { - return comV, nil - } - - v := reflect.New(rt) - rv := v.Elem() - - instance = v.Interface() - cr.instanceByType[td.RealType] = instance - err = nil - defer func() { - if nil != err { - instance = nil - delete(cr.instanceByType, td.RealType) - } - }() - - var ( - annotation cda.Annotation - fV interface{} - ) - - for _, fd := range td.Fields { - f := rv.FieldByName(fd.FieldName) - - if !f.IsValid() { - err = fmt.Errorf("DI: Field[%s] is not valid", fd.FieldName) - return - } - if !f.CanSet() { - err = fmt.Errorf("DI: Field[%s] can not set", fd.FieldName) - return - } - - if annotation = fd.GetAnnotationByType(cdia.InjectAnnotationType, false); nil != annotation { - if fV, err = cr.GetInstance(fd.Type); nil != err { - return - } - } - - if annotation = fd.GetAnnotationByType(cdia.ResourceAnnotationType, false); nil != annotation { - n := annotation.(*cdia.ResourceAnnotation).Name - if "" == n { - n = fd.FieldName - } - if fV, err = cr.GetInstanceByName(n); nil != err { - return - } - } - - if nil != err { - return - } - f.Set(reflect.ValueOf(fV)) - } - - return -} - -func GetInstanceByName(name string) (interface{}, error) { - return registry.GetInstanceByName(name) -} -func (cr *defaultComponentRegistry) GetInstanceByName(name string) (interface{}, error) { - v, ok := cr.resourceByName[name] - if ok { - return v, nil - } - return nil, fmt.Errorf("DI: Resource[%s] is not exist", name) -} - -// GetInstances returns instance of annotated -// n must be name of registered annotation -func GetInstances(ts []reflect.Type) ([]interface{}, error) { - return registry.GetInstances(ts) -} -func (cr *defaultComponentRegistry) GetInstances(ts []reflect.Type) ([]interface{}, error) { - var ( - i interface{} - err error - ) - instances := make([]interface{}, 0) - for _, t := range ts { - if i, err = cr.GetInstance(t); nil != err { - return nil, err - } - instances = append(instances, i) - } - - return instances, nil -} - -func GetInstancesByAnnotationType(t reflect.Type) ([]interface{}, error) { - return registry.GetInstancesByAnnotationType(t) -} -func (cr *defaultComponentRegistry) GetInstancesByAnnotationType(t reflect.Type) ([]interface{}, error) { - var ( - i interface{} - err error - ) - instances := make([]interface{}, 0) - - for _, td := range cr.definitionByType { - if nil != td.GetTypeAnnotationByType(t, true) { - if i, err = cr.GetInstance(td.Type); nil != err { - return nil, err - } - instances = append(instances, i) - } - } - - return instances, nil -} - -func GetTypeAnnotation(instanceType reflect.Type, annotationType reflect.Type) cda.Annotation { - return registry.GetTypeAnnotation(instanceType, annotationType) -} -func (cr *defaultComponentRegistry) GetTypeAnnotation(instanceType reflect.Type, annotationType reflect.Type) cda.Annotation { - def, ok := cr.definitionByType[instanceType] - if !ok { - return nil - } - - return def.GetTypeAnnotationByType(annotationType, false) -} -func GetMethodAnnotation(instanceType reflect.Type, annotationType reflect.Type, methodName string) cda.Annotation { - return registry.GetMethodAnnotation(instanceType, annotationType, methodName) -} -func (cr *defaultComponentRegistry) GetMethodAnnotation(instanceType reflect.Type, annotationType reflect.Type, methodName string) cda.Annotation { - def, ok := cr.definitionByType[instanceType] - if !ok { - return nil - } - - return def.GetMethodAnnotationByType(annotationType, methodName) -} - -func GetMethodAnnotations(instanceType reflect.Type, annotationType reflect.Type) map[string]cda.Annotation { - return registry.GetMethodAnnotations(instanceType, annotationType) -} -func (cr *defaultComponentRegistry) GetMethodAnnotations(instanceType reflect.Type, annotationType reflect.Type) map[string]cda.Annotation { - def, ok := cr.definitionByType[instanceType] - if !ok { - return nil - } - - return def.GetMethodAnnotationsByType(annotationType) -} - -func (cr *defaultComponentRegistry) buildDefinition(t reflect.Type) (*TypeDefinition, error) { - if nil == t { - return nil, fmt.Errorf("t[reflect.Type] is nil") - } - - rt, pkgName, tName := cur.GetTypeInfo(t) - td := &TypeDefinition{} - td.FullName = FullName(pkgName, tName) - td.PkgName = pkgName - td.TypeName = tName - td.Type = t - td.RealType = rt - td.Fields = make([]*FieldDefinition, 0) - - parseFields(rt, td) - - return td, nil -} - -func parseFields(t reflect.Type, td *TypeDefinition) { - // fields := make([]*FieldDefinition, 0) - rt, _, _ := cur.GetTypeInfo(t) - if reflect.Struct != rt.Kind() { - return - } - - for i := 0; i < rt.NumField(); i++ { - f := rt.Field(i) - - if f.Anonymous { - if parseAnonymousField(&f, td) { - continue - } - parseFields(f.Type, td) - } else { - if parseMethodAnnotation(&f, td) { - continue - } - as, err := cda.ParseAnnotation(f.Tag) - if nil != err { - return - } - if nil != as && 0 < len(as) { - fRT, fPkgName, fTName := cur.GetTypeInfo(f.Type) - - fd := &FieldDefinition{ - FieldName: f.Name, - PkgName: fPkgName, - TypeName: fTName, - Type: f.Type, - RealType: fRT, - Annotations: as, - } - td.Fields = append(td.Fields, fd) - } - } - } -} - -func parseAnonymousField(f *reflect.StructField, td *TypeDefinition) bool { - if parseTypeAnnotation(f, td) { - return true - } - return false -} - -func parseTypeAnnotation(f *reflect.StructField, td *TypeDefinition) bool { - // if !haveEmbeddingOf(cda.TypeAnnotationType, f.Type) { - // return - // } - if cda.TypeAnnotationType != f.Type { - return false - } - - as, err := cda.ParseAnnotation(f.Tag) - if nil != err { - return false - } - - if nil != as && 0 < len(as) { - td.TypeAnnotations = as - return true - } - return false -} - -func parseMethodAnnotation(f *reflect.StructField, td *TypeDefinition) bool { - if cda.MethodAnnotationType != f.Type { - return false - } - - as, err := cda.ParseAnnotation(f.Tag) - if nil != err { - return false - } - - if nil != as && 0 < len(as) { - if nil == td.MethodAnnotations { - td.MethodAnnotations = make(map[string]map[reflect.Type]cda.Annotation, 0) - } - td.MethodAnnotations[f.Name[1:]] = as - return true - } - return false -} - -func haveEmbeddingOf(t reflect.Type, target reflect.Type) bool { - if t == target { - return true - } - - rt, _, _ := cur.GetTypeInfo(target) - if reflect.Struct != rt.Kind() { - return false - } - - for i := 0; i < rt.NumField(); i++ { - f := rt.Field(i) - - if f.Anonymous { - if haveEmbeddingOf(t, f.Type) { - return true - } - } - } - return false -} diff --git a/registry/registry_test.go b/registry/registry_test.go deleted file mode 100644 index a6b2f69..0000000 --- a/registry/registry_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package registry - -import ( - "log" - "reflect" - "testing" - - "git.loafle.net/overflow/di-go/annotation" - cdia "git.loafle.net/overflow/di-go/injection/annotation" -) - -func TestRegisterType(t *testing.T) { - var ( - err error - css []interface{} - cs interface{} - ) - RegisterType(reflect.TypeOf((*AService)(nil))) - RegisterType(reflect.TypeOf((*BService)(nil))) - // RegisterType(reflect.TypeOf((*TestStruct2)(nil)), &cda.ComponentAnnotation{ - // Name: "test1", - // }) - // RegisterType(reflect.TypeOf((*TestStruct3)(nil)), &cda.ComponentAnnotation{ - // Name: "test2", - // }) - - // fs := getFields(reflect.TypeOf((*TestStruct3)(nil))) - // log.Printf("%v", fs) - - RegisterResource("List", []string{"dfdkf", "skgkfg"}) - - if css, err = GetInstancesByAnnotationType(cdia.ComponentAnnotationType); nil != err { - log.Printf("%v \n", err) - } - log.Printf("%v", css) - - if css, err = GetInstances([]reflect.Type{ - reflect.TypeOf((*AService)(nil)), - reflect.TypeOf((*BService)(nil)), - }); nil != err { - log.Printf("%v \n", err) - } - log.Printf("%v", css) - - if cs, err = GetInstance(reflect.TypeOf((*CService)(nil))); nil != err { - log.Printf("%v \n", err) - } - log.Printf("%v", cs.(*CService)) - -} - -type AService struct { - annotation.TypeAnnotation `annotation:"@Component(name='dkdkdf')"` - - NameA string -} - -type BService struct { - annotation.TypeAnnotation `annotation:"@Component()"` - - NameB string -} - -type CService struct { - AService *AService `annotation:"@Inject()"` - BService *BService `annotation:"@Inject()"` - List []string `annotation:"@Resource()"` -}