高级排程
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
2.5 KiB

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