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