dependency.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. package hero
  2. import (
  3. "fmt"
  4. "reflect"
  5. "github.com/kataras/iris/context"
  6. )
  7. type (
  8. // DependencyHandler is the native function declaration which implementors should return a value match to an input.
  9. DependencyHandler func(ctx *context.Context, input *Input) (reflect.Value, error)
  10. // Dependency describes the design-time dependency to be injected at serve time.
  11. // Contains its source location, the dependency handler (provider) itself and information
  12. // such as static for static struct values or explicit to bind a value to its exact DestType and not if just assignable to it (interfaces).
  13. Dependency struct {
  14. OriginalValue interface{} // Used for debugging and for logging only.
  15. Source Source
  16. Handle DependencyHandler
  17. // It's the exact type of return to bind, if declared to return <T>, otherwise nil.
  18. DestType reflect.Type
  19. Static bool
  20. // If true then input and dependnecy DestType should be indedical,
  21. // not just assiginable to each other.
  22. // Example of use case: depenendency like time.Time that we want to be bindable
  23. // only to time.Time inputs and not to a service with a `String() string` method that time.Time struct implements too.
  24. Explicit bool
  25. }
  26. )
  27. // Explicitly sets Explicit option to true.
  28. // See `Dependency.Explicit` field godoc for more.
  29. //
  30. // Returns itself.
  31. func (d *Dependency) Explicitly() *Dependency {
  32. d.Explicit = true
  33. return d
  34. }
  35. func (d *Dependency) String() string {
  36. sourceLine := d.Source.String()
  37. val := d.OriginalValue
  38. if val == nil {
  39. val = d.Handle
  40. }
  41. return fmt.Sprintf("%s (%#+v)", sourceLine, val)
  42. }
  43. // NewDependency converts a function or a function which accepts other dependencies or static struct value to a *Dependency.
  44. //
  45. // See `Container.Handler` for more.
  46. func NewDependency(dependency interface{}, funcDependencies ...*Dependency) *Dependency {
  47. if dependency == nil {
  48. panic(fmt.Sprintf("bad value: nil: %T", dependency))
  49. }
  50. if d, ok := dependency.(*Dependency); ok {
  51. // already a *Dependency.
  52. return d
  53. }
  54. v := valueOf(dependency)
  55. if !goodVal(v) {
  56. panic(fmt.Sprintf("bad value: %#+v", dependency))
  57. }
  58. dest := &Dependency{
  59. Source: newSource(v),
  60. OriginalValue: dependency,
  61. }
  62. if !resolveDependency(v, dest, funcDependencies...) {
  63. panic(fmt.Sprintf("bad value: could not resolve a dependency from: %#+v", dependency))
  64. }
  65. return dest
  66. }
  67. // DependencyResolver func(v reflect.Value, dest *Dependency) bool
  68. // Resolver DependencyResolver
  69. func resolveDependency(v reflect.Value, dest *Dependency, funcDependencies ...*Dependency) bool {
  70. return fromDependencyHandler(v, dest) ||
  71. fromStructValue(v, dest) ||
  72. fromFunc(v, dest) ||
  73. len(funcDependencies) > 0 && fromDependentFunc(v, dest, funcDependencies)
  74. }
  75. func fromDependencyHandler(_ reflect.Value, dest *Dependency) bool {
  76. // It's already on the desired form, just return it.
  77. dependency := dest.OriginalValue
  78. handler, ok := dependency.(DependencyHandler)
  79. if !ok {
  80. handler, ok = dependency.(func(*context.Context, *Input) (reflect.Value, error))
  81. if !ok {
  82. // It's almost a handler, only the second `Input` argument is missing.
  83. if h, is := dependency.(func(*context.Context) (reflect.Value, error)); is {
  84. handler = func(ctx *context.Context, _ *Input) (reflect.Value, error) {
  85. return h(ctx)
  86. }
  87. ok = is
  88. }
  89. }
  90. }
  91. if !ok {
  92. return false
  93. }
  94. dest.Handle = handler
  95. return true
  96. }
  97. func fromStructValue(v reflect.Value, dest *Dependency) bool {
  98. if !isFunc(v) {
  99. // It's just a static value.
  100. handler := func(*context.Context, *Input) (reflect.Value, error) {
  101. return v, nil
  102. }
  103. dest.DestType = v.Type()
  104. dest.Static = true
  105. dest.Handle = handler
  106. return true
  107. }
  108. return false
  109. }
  110. func fromFunc(v reflect.Value, dest *Dependency) bool {
  111. if !isFunc(v) {
  112. return false
  113. }
  114. typ := v.Type()
  115. numIn := typ.NumIn()
  116. numOut := typ.NumOut()
  117. if numIn == 0 {
  118. panic("bad value: function has zero inputs")
  119. }
  120. if numOut == 0 {
  121. panic("bad value: function has zero outputs")
  122. }
  123. if numOut == 2 && !isError(typ.Out(1)) {
  124. panic("bad value: second output should be an error")
  125. }
  126. if numOut > 2 {
  127. // - at least one output value
  128. // - maximum of two output values
  129. // - second output value should be a type of error.
  130. panic(fmt.Sprintf("bad value: function has invalid number of output arguments: %v", numOut))
  131. }
  132. var handler DependencyHandler
  133. firstIsContext := isContext(typ.In(0))
  134. secondIsInput := numIn == 2 && typ.In(1) == inputTyp
  135. onlyContext := (numIn == 1 && firstIsContext) || (numIn == 2 && firstIsContext && typ.IsVariadic())
  136. if onlyContext || (firstIsContext && secondIsInput) {
  137. handler = handlerFromFunc(v, typ)
  138. }
  139. if handler == nil {
  140. return false
  141. }
  142. dest.DestType = typ.Out(0)
  143. dest.Handle = handler
  144. return true
  145. }
  146. func handlerFromFunc(v reflect.Value, typ reflect.Type) DependencyHandler {
  147. // * func(Context, *Input) <T>, func(Context) <T>
  148. // * func(Context) <T>, func(Context) <T>
  149. // * func(Context, *Input) <T>, func(Context) (<T>, error)
  150. // * func(Context) <T>, func(Context) (<T>, error)
  151. hasErrorOut := typ.NumOut() == 2 // if two, always an error type here.
  152. hasInputIn := typ.NumIn() == 2 && typ.In(1) == inputTyp
  153. return func(ctx *context.Context, input *Input) (reflect.Value, error) {
  154. inputs := ctx.ReflectValue()
  155. if hasInputIn {
  156. inputs = append(inputs, input.selfValue)
  157. }
  158. results := v.Call(inputs)
  159. if hasErrorOut {
  160. return results[0], toError(results[1])
  161. }
  162. return results[0], nil
  163. }
  164. }
  165. func fromDependentFunc(v reflect.Value, dest *Dependency, funcDependencies []*Dependency) bool {
  166. // * func(<D>...) returns <T>
  167. // * func(<D>...) returns error
  168. // * func(<D>...) returns <T>, error
  169. typ := v.Type()
  170. if !isFunc(v) {
  171. return false
  172. }
  173. bindings := getBindingsForFunc(v, funcDependencies, -1 /* parameter bindings are disabled for depent dependencies */)
  174. numIn := typ.NumIn()
  175. numOut := typ.NumOut()
  176. // d1 = Logger
  177. // d2 = func(Logger) S1
  178. // d2 should be static: it accepts dependencies that are static
  179. // (note: we don't check the output argument(s) of this dependnecy).
  180. if numIn == len(bindings) {
  181. static := true
  182. for _, b := range bindings {
  183. if !b.Dependency.Static && matchDependency(b.Dependency, typ.In(b.Input.Index)) {
  184. static = false
  185. break
  186. }
  187. }
  188. if static {
  189. dest.Static = static
  190. }
  191. }
  192. firstOutIsError := numOut == 1 && isError(typ.Out(0))
  193. secondOutIsError := numOut == 2 && isError(typ.Out(1))
  194. handler := func(ctx *context.Context, _ *Input) (reflect.Value, error) {
  195. inputs := make([]reflect.Value, numIn)
  196. for _, binding := range bindings {
  197. input, err := binding.Dependency.Handle(ctx, binding.Input)
  198. if err != nil {
  199. if err == ErrSeeOther {
  200. continue
  201. }
  202. return emptyValue, err
  203. }
  204. inputs[binding.Input.Index] = input
  205. }
  206. outputs := v.Call(inputs)
  207. if firstOutIsError {
  208. return emptyValue, toError(outputs[0])
  209. } else if secondOutIsError {
  210. return outputs[0], toError(outputs[1])
  211. }
  212. return outputs[0], nil
  213. }
  214. dest.DestType = typ.Out(0)
  215. dest.Handle = handler
  216. return true
  217. }