123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- package di
- import (
- "fmt"
- "strings"
- "kpt-tmr-group/pkg/di/xreflect"
- "go.uber.org/dig"
- )
- // Option configures a Hub. It's included for future functionality;
- // currently, there are no concrete implementations.
- type Option = dig.Option
- // A ProvideOption modifies the default behavior of Provide.
- type ProvideOption = dig.ProvideOption
- // An InvokeOption modifies the default behavior of Invoke. It's included for
- // future functionality; currently, there are no concrete implementations.
- type InvokeOption = dig.InvokeOption
- // HubOption is an option configures an Hub using the functional options paradigm
- // popularized by Rob Pike. If you're unfamiliar with this style, see
- // https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html.
- type HubOption interface {
- fmt.Stringer
- Apply(hub *Hub)
- }
- // Options converts a collection of Options into a single Option. This allows
- // packages to bundle sophisticated functionality into easy-to-use Fx modules.
- // For example, a logging package might export a simple option like this:
- //
- // package logging
- //
- // var Module = fx.Provide(func() *log.Logger {
- // return log.New(os.Stdout, "", 0)
- // })
- //
- // A shared all-in-one microservice package could then use Options to bundle
- // logging with similar metrics, tracing, and gRPC modules:
- //
- // package server
- //
- // var Module = fx.Options(
- // logging.Module,
- // metrics.Module,
- // tracing.Module,
- // grpc.Module,
- // )
- //
- // Since this all-in-one module1 has a minimal API surface, it's easy to add
- // new functionality to it without breaking existing users. Individual
- // applications can take advantage of all this functionality with only one
- // line of code:
- //
- // app := di.New(server.Module)
- //
- // Use this pattern sparingly, since it limits the user's ability to customize
- // their application.
- func Options(opts ...HubOption) HubOption {
- return optionGroup(opts)
- }
- type optionGroup []HubOption
- func (og optionGroup) Apply(hub *Hub) {
- for _, opt := range og {
- opt.Apply(hub)
- }
- }
- func (og optionGroup) String() string {
- items := make([]string, len(og))
- for i, opt := range og {
- items[i] = fmt.Sprint(opt)
- }
- return fmt.Sprintf("di.Options(%s)", strings.Join(items, ", "))
- }
- // Annotation define annotated and apply to Provided
- // Annotation provides instantiated values for dependency injection as if
- // they had been provided using a constructor that simply returns them.
- // The most specific type of each value (as determined by reflection) is used.
- //
- // type K0 struct {
- // Closed bool
- // }
- //
- // func (k *K0) Close() {
- // k.Closed = true
- // }
- //
- // k0 := &K0{}
- // var module = Annotation(func(ann *Annotated) {
- // ann.Target = func() *K0 { return k0 }
- // ann.Close = k0.Close
- // })
- //
- // hub, err := di.New(module)
- func Annotation(f func(ann *Annotated)) HubOption {
- annotation := &Annotated{}
- f(annotation)
- return provideOption{
- Targets: []interface{}{*annotation},
- Stack: xreflect.CallerStack(1, 0),
- }
- }
- // Provide registers any number of constructor functions, teaching the
- // application how to instantiate various types. The supplied constructor
- // function(s) may depend on other types available in the application, must
- // return one or more objects, and may return an error. For example:
- //
- // // Constructs type *C, depends on *A and *B.
- // func(*A, *B) *C
- //
- // // Constructs type *C, depends on *A and *B, and indicates failure by
- // // returning an error.
- // func(*A, *B) (*C, error)
- //
- // // Constructs types *B and *C, depends on *A, and can fail.
- // func(*A) (*B, *C, error)
- func Provide(constructors ...interface{}) HubOption {
- // check no nil or error
- for _, value := range constructors {
- switch value.(type) {
- case nil:
- panic("untyped nil passed to di.Provide")
- case error:
- panic("error value passed to di.Provide")
- }
- }
- return provideOption{
- Targets: constructors,
- Stack: xreflect.CallerStack(1, 0),
- }
- }
- type provideOption struct {
- Targets []interface{}
- Stack xreflect.Stack
- }
- func (o provideOption) Apply(hub *Hub) {
- for _, target := range o.Targets {
- hub.provides = append(hub.provides, Provided{
- Target: target,
- Stack: o.Stack,
- })
- }
- }
- func (o provideOption) String() string {
- items := make([]string, len(o.Targets))
- for i, c := range o.Targets {
- items[i] = xreflect.FuncName(c)
- }
- return fmt.Sprintf("fx.Provide(%s)", strings.Join(items, ", "))
- }
- // ValidateHub validates that supplied graph would run and is not missing any dependencies.
- func ValidateHub(v bool) HubOption {
- return validateOption{validate: v}
- }
- type validateOption struct {
- validate bool
- }
- func (o validateOption) Apply(hub *Hub) {
- hub.validate = o.validate
- }
- func (o validateOption) String() string {
- return fmt.Sprintf("fx.validate(%v)", o.validate)
- }
|