go_dreamfactory/modules/comp_gate.go
2023-06-06 09:52:44 +08:00

172 lines
5.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package modules
import (
"fmt"
"go_dreamfactory/comm"
"go_dreamfactory/pb"
"log"
"reflect"
"strings"
"unicode"
"unicode/utf8"
"go_dreamfactory/lego/base"
"go_dreamfactory/lego/core"
"go_dreamfactory/lego/core/cbase"
"google.golang.org/protobuf/proto"
)
/*
模块网关组件的基类实现 模块接收用户的消息请求都需要通过装备继承此组件的api组件来实现
*/
// var typeOfContext = reflect.TypeOf((*context.Context)(nil)).Elem()
var typeOfSession = reflect.TypeOf((*comm.IUserSession)(nil)).Elem()
var typeOfMessage = reflect.TypeOf((*proto.Message)(nil)).Elem()
var typeOfErrorCode = reflect.TypeOf((*pb.ErrorCode)(nil)).Elem()
var typeOfErrorData = reflect.TypeOf((*pb.ErrorData)(nil))
var typeOfError = reflect.TypeOf((*error)(nil)).Elem()
/*
模块 网关组件 接收处理用户传递消息
*/
type MCompGate struct {
cbase.ModuleCompBase
service base.IRPCXService //rpc服务对象
module core.IModule //当前业务模块
comp core.IModuleComp //网关组件自己
scomp comm.ISC_GateRouteComp
}
//组件初始化接口
func (this *MCompGate) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) {
this.ModuleCompBase.Init(service, module, comp, options)
this.service = service.(base.IRPCXService)
this.module = module
this.comp = comp
return
}
//组件启动接口启动时将自己接收用户消息的处理函数注册到services/comp_gateroute.go 对象中
func (this *MCompGate) Start() (err error) {
if err = this.ModuleCompBase.Start(); err != nil {
return
}
var comp core.IServiceComp
//注册远程路由
if comp, err = this.service.GetComp(comm.SC_ServiceGateRouteComp); err != nil {
return
}
this.scomp = comp.(comm.ISC_GateRouteComp)
this.suitableMethods()
return
}
//反射注册相关接口道services/comp_gateroute.go 对象中
func (this *MCompGate) suitableMethods() {
typ := reflect.TypeOf(this.comp)
for m := 0; m < typ.NumMethod(); m++ {
method := typ.Method(m)
mname := method.Name
if mname == "Start" ||
mname == "Init" ||
mname == "Destroy" ||
strings.HasSuffix(mname, "Check") {
continue
}
this.reflectionRouteHandle(typ, method)
}
}
//反射注册路由处理函数
func (this *MCompGate) reflectionRouteHandle(typ reflect.Type, method reflect.Method) (ret bool) {
mtype := method.Type
mname := method.Name
if method.PkgPath != "" {
log.Panicf("反射注册用户处理函数错误 [%s-%s] Api接口格式错误", this.module.GetType(), mname)
return
}
if mtype.NumIn() != 3 {
log.Panicf("反射注册用户处理函数错误 [%s-%s] Api接口格式错误", this.module.GetType(), mname)
return
}
sessionType := mtype.In(1)
if !sessionType.Implements(typeOfSession) {
log.Panicf("反射注册用户处理函数错误 [%s-%s] Api接口格式错误", this.module.GetType(), mname)
return
}
agrType := mtype.In(2)
if !agrType.Implements(typeOfMessage) {
log.Panicf("反射注册用户处理函数错误 [%s-%s] Api接口格式错误", this.module.GetType(), mname)
return
}
if mtype.NumOut() != 1 {
log.Panicf("反射注册用户处理函数错误 [%s-%s] Api接口格式错误", this.module.GetType(), mname)
return
}
// returnCodeType := mtype.Out(0)
// if returnCodeType != typeOfErrorCode {
// log.Panicf("反射注册用户处理函数错误 [%s-%s] Api接口格式错误", this.module.GetType(), mname)
// return
// }
returnDataType := mtype.Out(0)
if returnDataType != typeOfErrorData {
log.Panicf("反射注册用户处理函数错误 [%s-%s] Api接口格式错误", this.module.GetType(), mname)
return
}
//寻找校验函数
check, ok := typ.MethodByName(mname + "Check")
if !ok {
log.Panicf("反射注册用户处理函数错误 [%s-%s]没有对应的校验函数", this.module.GetType(), mname)
return
}
if err := this.reflectionRouteCheck(check, agrType); err == nil {
this.scomp.RegisterRoute(fmt.Sprintf("%s.%s", this.module.GetType(), strings.ToLower(mname)), reflect.ValueOf(this.comp), agrType, method)
} else {
log.Panicf("反射注册用户处理函数错误 [%s-%s]校验函数格式异常:%v", this.module.GetType(), mname, err)
return
}
return true
}
//反射注册路由校验函数
func (this *MCompGate) reflectionRouteCheck(method reflect.Method, msgtype reflect.Type) error {
mtype := method.Type
if method.PkgPath != "" {
return fmt.Errorf("method.PkgPath:%v", method.PkgPath)
}
if mtype.NumIn() != 3 {
return fmt.Errorf("mtype.NumIn():%v", mtype.NumIn())
}
sessionType := mtype.In(1)
if !sessionType.Implements(typeOfSession) {
return fmt.Errorf("sessionType:%T", sessionType)
}
agrType := mtype.In(2)
if agrType != msgtype {
return fmt.Errorf("replyType:%T msgtype:%T", agrType, msgtype)
}
if mtype.NumOut() != 1 {
return fmt.Errorf("mtype.NumOut():%d", mtype.NumOut())
}
returnDataType := mtype.Out(0)
if returnDataType != typeOfErrorData {
return fmt.Errorf("returnType:%T", returnDataType)
}
return nil
}
func (this *MCompGate) isExportedOrBuiltinType(t reflect.Type) bool {
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
return this.isExported(t.Name()) || t.PkgPath() == ""
}
func (this *MCompGate) isExported(name string) bool {
rune, _ := utf8.DecodeRuneInString(name)
return unicode.IsUpper(rune)
}