service.go 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package service
  2. import (
  3. "errors"
  4. "git.bvbej.com/bvbej/base-golang/pkg/websocket/util"
  5. "reflect"
  6. "strings"
  7. "git.bvbej.com/bvbej/base-golang/pkg/websocket/peer"
  8. )
  9. type Handler struct {
  10. Receiver reflect.Value // 值
  11. Method reflect.Method // 方法
  12. Type reflect.Type // 类型
  13. IsRawArg bool // 数据是否需要序列化
  14. }
  15. type Service struct {
  16. Name string // 服务名
  17. Type reflect.Type // 服务类型
  18. Receiver reflect.Value // 服务值
  19. Handlers map[string]*Handler // 注册的方法列表
  20. Component Component
  21. }
  22. func NewService(comp Component) *Service {
  23. s := &Service{
  24. Type: reflect.TypeOf(comp),
  25. Receiver: reflect.ValueOf(comp),
  26. Component: comp,
  27. }
  28. s.Name = strings.ToLower(reflect.Indirect(s.Receiver).Type().Name())
  29. //调用初始化方法
  30. s.Component.Init()
  31. return s
  32. }
  33. func (s *Service) SuitableHandlerMethods(typ reflect.Type) map[string]*Handler {
  34. methods := make(map[string]*Handler)
  35. for m := 0; m < typ.NumMethod(); m++ {
  36. method := typ.Method(m)
  37. mt := method.Type
  38. mn := method.Name
  39. if isHandlerMethod(method) {
  40. raw := false
  41. if mt.In(2) == typeOfBytes {
  42. raw = true
  43. }
  44. mn = strings.ToLower(mn)
  45. methods[mn] = &Handler{Method: method, Type: mt.In(2), IsRawArg: raw}
  46. }
  47. }
  48. return methods
  49. }
  50. func (s *Service) ExtractHandler() error {
  51. typeName := reflect.Indirect(s.Receiver).Type().Name()
  52. if typeName == "" {
  53. return errors.New("no service name for type " + s.Type.String())
  54. }
  55. if !util.IsExported(typeName) {
  56. return errors.New("type " + typeName + " is not exported")
  57. }
  58. s.Handlers = s.SuitableHandlerMethods(s.Type)
  59. for i := range s.Handlers {
  60. s.Handlers[i].Receiver = s.Receiver
  61. }
  62. if reflect.Indirect(s.Receiver).NumField() > 0 {
  63. filedNum := reflect.Indirect(s.Receiver).NumField()
  64. for i := 0; i < filedNum; i++ {
  65. ty := reflect.Indirect(s.Receiver).Field(i).Type().Name()
  66. if ty == ChildName {
  67. h := s.SuitableHandlerMethods(reflect.Indirect(s.Receiver).Field(i).Elem().Type())
  68. for ih, v := range h {
  69. s.Handlers[ih] = v
  70. s.Handlers[ih].Receiver = reflect.Indirect(s.Receiver).Field(i).Elem()
  71. }
  72. }
  73. }
  74. }
  75. if len(s.Handlers) == 0 {
  76. str := "service: "
  77. method := s.SuitableHandlerMethods(reflect.PtrTo(s.Type))
  78. if len(method) != 0 {
  79. str = "type " + s.Name + " has no exported methods of suitable type (hint: pass a pointer to value of that type)"
  80. } else {
  81. str = "type " + s.Name + " has no exported methods of suitable type"
  82. }
  83. return errors.New(str)
  84. }
  85. return nil
  86. }
  87. func (s *Service) OnSessionClose(session *peer.Session) bool {
  88. return s.Component.OnSessionClose(session)
  89. }