package component import ( "fmt" "reflect" ) type ( // Handler 消息处理器,当前仅支持单个自定义参数 Handler struct { Receiver reflect.Value // 方法接收者 Method reflect.Method // 方法存根 Type reflect.Type // 方法参数类型 IsRawArg bool // 数据是否需要被序列化,true代表不需要 } // Service 服务,绑定消息处理器用以处理发生的消息 Service struct { Name string // 服务名称 Type reflect.Type // 接收者类型 Receiver reflect.Value // 该服务下所有方法的接收者 Handlers map[string]*Handler // 该服务下属的所有方法 Options options // options } ) func NewService(comp Component, opts []Option) *Service { s := &Service{ Type: reflect.TypeOf(comp), Receiver: reflect.ValueOf(comp), } // apply options for _, opt := range opts { opt(&s.Options) } if name := s.Options.serviceName; name != "" { s.Name = name } else { s.Name = reflect.Indirect(s.Receiver).Type().Name() } return s } // suitableHandlerMethods 反射装填指定type-service的所有认定为handlerMethod的方法 func (s *Service) suitableHandlerMethods(typ reflect.Type) map[string]*Handler { methods := make(map[string]*Handler) for m := 0; m < typ.NumMethod(); m++ { method := typ.Method(m) mt := method.Type mn := method.Name if isHandlerMethod(method) { raw := false if mt.In(2) == typeOfBytes { raw = true } // rewrite handler name if s.Options.methodNameFunc != nil { mn = s.Options.methodNameFunc(mn) } methods[mn] = &Handler{Method: method, Type: mt.In(2), IsRawArg: raw} } } return methods } // ExtractHandler 反射提取满足以下条件的方法 // - 两个显示入参 // - 第一个是 *net.request // - 另一个是 []byte 或者 任意指针类型 pointer func (s *Service) ExtractHandler() error { typeName := reflect.Indirect(s.Receiver).Type().Name() if typeName == "" { return fmt.Errorf("no service name for type %s", s.Type.String()) } if !isExported(typeName) { return fmt.Errorf("type %s is not exported", typeName) } // suitable handlers s.Handlers = s.suitableHandlerMethods(s.Type) if len(s.Handlers) == 0 { method := s.suitableHandlerMethods(reflect.PtrTo(s.Type)) if len(method) == 0 { return fmt.Errorf("type %s has no exported methods of suitable type (hint: pass a pointer to value of that type)", s.Name) } else { return fmt.Errorf("type %s has no exported methods of suitable type") } } for _, handler := range s.Handlers { handler.Receiver = s.Receiver } return nil }