|
// 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
|
|
}
|