// Copyright (c) Shenyang Leading Edge Intelligent Technology Co., Ltd. All rights reserved. package container import ( "errors" "fmt" "reflect" "strings" ) type DefaultComponentContainer struct { methodMapping map[string]func([]reflect.Value) []reflect.Value } func NewDefaultComponentContainer() *DefaultComponentContainer { return &DefaultComponentContainer{ methodMapping: make(map[string]func([]reflect.Value) []reflect.Value), } } func (container *DefaultComponentContainer) RegisterService(factory interface{}) error { valueOfFactory := reflect.ValueOf(factory) typeOfFactory := valueOfFactory.Type() if typeOfFactory.Kind() != reflect.Func { return errors.New("工厂必须是func!") } if typeOfFactory.NumIn() != 0 { return errors.New("工厂不能有参数!") } if typeOfFactory.NumOut() < 1 { return errors.New("工厂必值需有返回值!") } if typeOfFactory.NumOut() > 1 { return errors.New("工厂只能有一个返回值!") } if typeOfFactory.Out(0).Kind() != reflect.Interface { return errors.New("工厂的返回值必需是interface!") } serviceType := typeOfFactory.Out(0) serviceName := serviceType.Name() if serviceType.Kind() != reflect.Interface { return errors.New(fmt.Sprintf("服务类型必须是接口! 服务: %s", serviceName)) } if !strings.HasSuffix(serviceName, ServiceNameSuffix) { return errors.New(fmt.Sprintf("服务%s接口名称的后缀不是%s!", serviceType.Name(), ServiceNameSuffix)) } packageList := strings.Split(serviceType.PkgPath(), PathSeparator) servicePackagePath := "" for index, packageName := range packageList { if strings.ToLower(packageName) == ServicesPackageName { servicePackagePath = strings.Join(packageList[index+1:], PathSeparator) break } } if servicePackagePath == "" { return errors.New(fmt.Sprintf("服务%s不在包%s或他的子包之下!", serviceType.Name(), ServicesPackageName)) } for i := 0; i < serviceType.NumMethod(); i++ { method := serviceType.Method(i) serviceValue := valueOfFactory.Call(emptyParameters)[0] methodValue := serviceValue.MethodByName(method.Name) methodFullName := fmt.Sprintf("%s/%s.%s", servicePackagePath, serviceType.Name(), method.Name) container.methodMapping[methodFullName] = methodValue.Call } return nil } func (container *DefaultComponentContainer) GetServiceCaller(methodFullName string) func([]reflect.Value) []reflect.Value { caller, ok := container.methodMapping[methodFullName] if ok { return caller } return nil }