inject.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // Package inject provides utilities for mapping and injecting dependencies in various ways.
  2. package inject
  3. import (
  4. "fmt"
  5. "reflect"
  6. )
  7. // Injector represents an interface for mapping and injecting dependencies into structs
  8. // and function arguments.
  9. type Injector interface {
  10. Applicator
  11. Invoker
  12. TypeMapper
  13. // SetParent sets the parent of the injector. If the injector cannot find a
  14. // dependency in its Type map it will check its parent before returning an
  15. // error.
  16. SetParent(Injector)
  17. }
  18. // Applicator represents an interface for mapping dependencies to a struct.
  19. type Applicator interface {
  20. // Maps dependencies in the Type map to each field in the struct
  21. // that is tagged with 'inject'. Returns an error if the injection
  22. // fails.
  23. Apply(interface{}) error
  24. }
  25. // Invoker represents an interface for calling functions via reflection.
  26. type Invoker interface {
  27. // Invoke attempts to call the interface{} provided as a function,
  28. // providing dependencies for function arguments based on Type. Returns
  29. // a slice of reflect.Value representing the returned values of the function.
  30. // Returns an error if the injection fails.
  31. Invoke(interface{}) ([]reflect.Value, error)
  32. }
  33. // TypeMapper represents an interface for mapping interface{} values based on type.
  34. type TypeMapper interface {
  35. // Maps the interface{} value based on its immediate type from reflect.TypeOf.
  36. Map(interface{}) TypeMapper
  37. // Maps the interface{} value based on the pointer of an Interface provided.
  38. // This is really only useful for mapping a value as an interface, as interfaces
  39. // cannot at this time be referenced directly without a pointer.
  40. MapTo(interface{}, interface{}) TypeMapper
  41. // Provides a possibility to directly insert a mapping based on type and value.
  42. // This makes it possible to directly map type arguments not possible to instantiate
  43. // with reflect like unidirectional channels.
  44. Set(reflect.Type, reflect.Value) TypeMapper
  45. // Returns the Value that is mapped to the current type. Returns a zeroed Value if
  46. // the Type has not been mapped.
  47. Get(reflect.Type) reflect.Value
  48. }
  49. type injector struct {
  50. values map[reflect.Type]reflect.Value
  51. parent Injector
  52. }
  53. // InterfaceOf dereferences a pointer to an Interface type.
  54. // It panics if value is not an pointer to an interface.
  55. func InterfaceOf(value interface{}) reflect.Type {
  56. t := reflect.TypeOf(value)
  57. for t.Kind() == reflect.Ptr {
  58. t = t.Elem()
  59. }
  60. if t.Kind() != reflect.Interface {
  61. panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")
  62. }
  63. return t
  64. }
  65. // New returns a new Injector.
  66. func New() Injector {
  67. return &injector{
  68. values: make(map[reflect.Type]reflect.Value),
  69. }
  70. }
  71. // Invoke attempts to call the interface{} provided as a function,
  72. // providing dependencies for function arguments based on Type.
  73. // Returns a slice of reflect.Value representing the returned values of the function.
  74. // Returns an error if the injection fails.
  75. // It panics if f is not a function
  76. func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
  77. t := reflect.TypeOf(f)
  78. var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
  79. for i := 0; i < t.NumIn(); i++ {
  80. argType := t.In(i)
  81. val := inj.Get(argType)
  82. if !val.IsValid() {
  83. return nil, fmt.Errorf("Value not found for type %v", argType)
  84. }
  85. in[i] = val
  86. }
  87. return reflect.ValueOf(f).Call(in), nil
  88. }
  89. // Maps dependencies in the Type map to each field in the struct
  90. // that is tagged with 'inject'.
  91. // Returns an error if the injection fails.
  92. func (inj *injector) Apply(val interface{}) error {
  93. v := reflect.ValueOf(val)
  94. for v.Kind() == reflect.Ptr {
  95. v = v.Elem()
  96. }
  97. if v.Kind() != reflect.Struct {
  98. return nil // Should not panic here ?
  99. }
  100. t := v.Type()
  101. for i := 0; i < v.NumField(); i++ {
  102. f := v.Field(i)
  103. structField := t.Field(i)
  104. if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") {
  105. ft := f.Type()
  106. v := inj.Get(ft)
  107. if !v.IsValid() {
  108. return fmt.Errorf("Value not found for type %v", ft)
  109. }
  110. f.Set(v)
  111. }
  112. }
  113. return nil
  114. }
  115. // Maps the concrete value of val to its dynamic type using reflect.TypeOf,
  116. // It returns the TypeMapper registered in.
  117. func (i *injector) Map(val interface{}) TypeMapper {
  118. i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)
  119. return i
  120. }
  121. func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {
  122. i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)
  123. return i
  124. }
  125. // Maps the given reflect.Type to the given reflect.Value and returns
  126. // the Typemapper the mapping has been registered in.
  127. func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {
  128. i.values[typ] = val
  129. return i
  130. }
  131. func (i *injector) Get(t reflect.Type) reflect.Value {
  132. val := i.values[t]
  133. if val.IsValid() {
  134. return val
  135. }
  136. // no concrete types found, try to find implementors
  137. // if t is an interface
  138. if t.Kind() == reflect.Interface {
  139. for k, v := range i.values {
  140. if k.Implements(t) {
  141. val = v
  142. break
  143. }
  144. }
  145. }
  146. // Still no type found, try to look it up on the parent
  147. if !val.IsValid() && i.parent != nil {
  148. val = i.parent.Get(t)
  149. }
  150. return val
  151. }
  152. func (i *injector) SetParent(parent Injector) {
  153. i.parent = parent
  154. }