di

package
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 15, 2022 License: BSD-3-Clause Imports: 5 Imported by: 0

Documentation

Overview

Package di provides dependency injection for the Iris Hero and Iris MVC new features. It's used internally by "hero" and "mvc" packages.

Index

Constants

This section is empty.

Variables

View Source
var EmptyIn = []reflect.Value{}

EmptyIn is just an empty slice of reflect.Value.

Functions

func IndirectType

func IndirectType(typ reflect.Type) reflect.Type

IndirectType returns the value of a pointer-type "typ". If "typ" is a pointer, array, chan, map or slice it returns its Elem, otherwise returns the typ as it's.

func IndirectValue

func IndirectValue(v reflect.Value) reflect.Value

IndirectValue returns the reflect.Value that "v" points to. If "v" is a nil pointer, Indirect returns a zero Value. If "v" is not a pointer, Indirect returns v.

func IsContext

func IsContext(inTyp reflect.Type) bool

IsContext returns true if the "inTyp" is a type of Context.

func IsError

func IsError(typ reflect.Type) bool

IsError returns true if "typ" is type of `error`.

func IsFunc

func IsFunc(kindable interface {
	Kind() reflect.Kind
}) bool

IsFunc returns true if the passed type is function.

func IsNil

func IsNil(v reflect.Value) bool

IsNil same as `reflect.IsNil` but a bit safer to use, returns false if not a correct type.

func IsZero

func IsZero(v reflect.Value) bool

IsZero returns true if a value is nil. Remember; fields to be checked should be exported otherwise it returns false. Notes for users: Boolean's zero value is false, even if not set-ed. UintXX are not zero on 0 because they are pointers to.

func LookupNonZeroFieldsValues

func LookupNonZeroFieldsValues(v reflect.Value, skipUnexported bool) (bindValues []reflect.Value)

LookupNonZeroFieldsValues lookup for filled fields based on the "v" struct value instance. It returns a slice of reflect.Value (same type as `Values`) that can be binded, like the end-developer's custom values.

func MakeReturnValue

func MakeReturnValue(fn reflect.Value, errorHandler ErrorHandler) (func(context.Context) reflect.Value, reflect.Type, error)

MakeReturnValue takes any function that accept custom values and returns something, it returns a binder function, which accepts a slice of reflect.Value and returns a single one reflect.Value for that. It's being used to resolve the input parameters on a "x" consumer faster.

The "fn" can have the following form: `func(myService) MyViewModel`.

The return type of the "fn" should be a value instance, not a pointer. The binder function should return just one value.

func NumFields

func NumFields(elemTyp reflect.Type, skipUnexported bool) int

NumFields returns the total number of fields, and the embedded, even if the embedded struct is not exported, it will check for its exported fields.

func ValueOf

func ValueOf(o interface{}) reflect.Value

ValueOf returns the reflect.Value of "o". If "o" is already a reflect.Value returns "o".

func ValuesOf

func ValuesOf(valuesAsInterface []interface{}) (values []reflect.Value)

ValuesOf same as `ValueOf` but accepts a slice of somethings and returns a slice of reflect.Value.

Types

type AutoBindingValue

type AutoBindingValue struct{}

AutoBindingValue a fake type to expliclty set the return value of hero.AutoBinding.

type BindObject

type BindObject struct {
	Type  reflect.Type // the Type of 'Value' or the type of the returned 'ReturnValue' .
	Value reflect.Value

	BindType    BindType
	ReturnValue func(ctx context.Context) reflect.Value
}

BindObject contains the dependency value's read-only information. FuncInjector and StructInjector keeps information about their input arguments/or fields, these properties contain a `BindObject` inside them.

func MakeBindObject

func MakeBindObject(v reflect.Value, errorHandler ErrorHandler) (b BindObject, err error)

MakeBindObject accepts any "v" value, struct, pointer or a function and a type checker that is used to check if the fields (if "v.elem()" is struct) or the input arguments (if "v.elem()" is func) are valid to be included as the final object's dependencies, even if the caller added more the "di" is smart enough to select what each "v" needs and what not before serve time.

func (*BindObject) Assign

func (b *BindObject) Assign(ctx context.Context, toSetter func(reflect.Value))

Assign sets the values to a setter, "toSetter" contains the setter, so the caller can use it for multiple and different structs/functions as well.

func (*BindObject) IsAssignable

func (b *BindObject) IsAssignable(to reflect.Type) bool

IsAssignable checks if "to" type can be used as "b.Value/ReturnValue".

type BindType

type BindType uint32

BindType is the type of a binded object/value, it's being used to check if the value is accessible after a function call with a "ctx" when needed ( Dynamic type) or it's just a struct value (a service | Static type).

const (
	// Static is the simple assignable value, a static value.
	Static BindType = iota
	// Dynamic returns a value but it depends on some input arguments from the caller,
	// on serve time.
	Dynamic
)

type D

type D struct {
	Values
	// contains filtered or unexported fields
}

D is the Dependency Injection container, it contains the Values that can be changed before the injectors. `Struct` and the `Func` methods returns an injector for specific struct instance-value or function.

func New

func New() *D

New creates and returns a new Dependency Injection container. See `Values` field and `Func` and `Struct` methods for more.

func (*D) Clone

func (d *D) Clone() *D

Clone returns a new Dependency Injection container, it adopts the parent's (current "D") hijacker, good func type checker, sorter and all dependencies values.

func (*D) ErrorHandler

func (d *D) ErrorHandler(errorHandler ErrorHandler) *D

ErrorHandler adds a handler which will be fired when a handler's second output argument is error and it's not nil or when a request-scoped dynamic function dependency's second output argument is error and it's not nil.

func (*D) FallbackBinder

func (d *D) FallbackBinder(fallbackBinder FallbackBinder) *D

FallbackBinder adds a binder which will handle any oprhan input values. See `FallbackBinder` type.

func (*D) Func

func (d *D) Func(fn interface{}) *FuncInjector

Func is being used to return a new injector based on a function, if it contains input arguments that the types of those are matching with one or more of the `Values` then they are binded to the function's input argument when called with the injector's `Inject` method.

func (*D) Sort

func (d *D) Sort(with Sorter) *D

Sort sets the fields and valid bindable values sorter for struct injection.

func (*D) Struct

func (d *D) Struct(s interface{}) *StructInjector

Struct is being used to return a new injector based on a struct value instance, if it contains fields that the types of those are matching with one or more of the `Values` then they are binded with the injector's `Inject` and `InjectElem` methods.

type ErrorHandler

type ErrorHandler interface {
	HandleError(ctx context.Context, err error)
}

ErrorHandler is the optional interface to handle errors per hero func, see `mvc/Application#HandleError` for MVC application-level error handler registration too.

Handles non-nil errors return from a hero handler or a controller's method (see `DispatchFuncResult`) and (from v12.1.8) the error may return from a request-scoped dynamic dependency (see `MakeReturnValue`).

var DefaultErrorHandler ErrorHandler = ErrorHandlerFunc(func(ctx context.Context, err error) {
	if err == nil {
		return
	}

	ctx.StatusCode(400)
	ctx.WriteString(err.Error())
	ctx.StopExecution()
})

DefaultErrorHandler is the default error handler will be fired on any error from registering a request-scoped dynamic dependency and on a controller's method failure.

type ErrorHandlerFunc

type ErrorHandlerFunc func(ctx context.Context, err error)

ErrorHandlerFunc implements the `ErrorHandler`. It describes the type defnition for an error handler.

func (ErrorHandlerFunc) HandleError

func (fn ErrorHandlerFunc) HandleError(ctx context.Context, err error)

HandleError fires when the `DispatchFuncResult` or `MakereturnValue` return a non-nil error.

type FallbackBinder

type FallbackBinder func(ctx context.Context, input OrphanInput) (reflect.Value, error)

FallbackBinder represents a handler of oprhan input values, handler's input arguments or controller's fields.

var DefaultFallbackBinder FallbackBinder = func(ctx context.Context, input OrphanInput) (newValue reflect.Value, err error) {
	wasPtr := input.Type.Kind() == reflect.Ptr

	newValue = reflect.New(IndirectType(input.Type))
	ptr := newValue.Interface()

	switch ctx.GetContentTypeRequested() {
	case context.ContentXMLHeaderValue:
		err = ctx.ReadXML(ptr)
	case context.ContentYAMLHeaderValue:
		err = ctx.ReadYAML(ptr)
	case context.ContentFormHeaderValue:
		err = ctx.ReadQuery(ptr)
	case context.ContentFormMultipartHeaderValue:
		err = ctx.ReadForm(ptr)
	default:
		err = ctx.ReadJSON(ptr)

	}

	if !wasPtr {
		newValue = newValue.Elem()
	}

	return newValue, err
}

DefaultFallbackBinder used to bind any oprhan inputs. Its error is handled by the `ErrorHandler`.

type FuncInjector

type FuncInjector struct {
	FallbackBinder FallbackBinder
	ErrorHandler   ErrorHandler

	// Length is the number of the valid, final binded input arguments.
	Length int
	// Valid is True when `Length` is > 0, it's statically set-ed for
	// performance reasons.
	Has bool
	// contains filtered or unexported fields
}

FuncInjector keeps the data that are needed in order to do the binding injection as fast as possible and with the best possible and safest way.

func Func

func Func(fn interface{}, values ...reflect.Value) *FuncInjector

Func is being used to return a new injector based on a function, if it contains input arguments that the types of those are matching with one or more of the `Values` then they are binded to the function's input argument when called with the injector's `Inject` method.

func MakeFuncInjector

func MakeFuncInjector(fn reflect.Value, values ...reflect.Value) *FuncInjector

MakeFuncInjector returns a new func injector, which will be the object that the caller should use to bind input arguments of the "fn" function.

The hijack and the goodFunc are optional, the "values" is the dependencies collection.

func (*FuncInjector) Call

func (s *FuncInjector) Call(ctx context.Context) []reflect.Value

Call calls the "Inject" with a new slice of input arguments that are computed by the length of the input argument from the MakeFuncInjector's "fn" function.

If the function needs a receiver, so the caller should be able to in[0] = receiver before injection, then the `Inject` method should be used instead.

func (*FuncInjector) Inject

func (s *FuncInjector) Inject(ctx context.Context, in *[]reflect.Value)

Inject accepts an already created slice of input arguments and fills them, the "ctx" is optional and it's used on the dependencies that depends on one or more input arguments, these are the "ctx".

func (*FuncInjector) Retry

func (s *FuncInjector) Retry(retryFn func(inIndex int, inTyp reflect.Type, remainingValues Values) (reflect.Value, bool)) bool

Retry used to add missing dependencies, i.e path parameter builtin bindings if not already exists in the `hero.Handler`, once, only for that func injector.

func (*FuncInjector) String

func (s *FuncInjector) String() (trace string)

String returns a debug trace text.

type OrphanInput

type OrphanInput struct {
	// Index int // function or struct field index.
	Type reflect.Type
}

OrphanInput represents an input without registered dependency. Used to help the framework (or the caller) auto-resolve it by the request.

type Scope

type Scope uint8

Scope is the struct injector's struct value scope/permant state. See `Stateless` and `Singleton`.

const (
	// Stateless is the scope that the struct should be different on each binding,
	// think it like `Request Scoped`, per-request struct for mvc.
	Stateless Scope = iota
	// Singleton is the scope that the struct is the same
	// between calls, it has no dynamic dependencies or
	// any unexported fields that is not seted on creation,
	// so it doesn't need to be created on each call/request.
	Singleton
)

func (Scope) String

func (scope Scope) String() string

Return "Stateless" for 0 or "Singleton" for 1.

type Sorter

type Sorter func(t1 reflect.Type, t2 reflect.Type) bool

Sorter is the type for sort customization of a struct's fields and its available bindable values.

Sorting applies only when a field can accept more than one registered value.

var SortByNumMethods Sorter = func(t1 reflect.Type, t2 reflect.Type) bool {
	if t1.Kind() != t2.Kind() {
		return true
	}

	if k := t1.Kind(); k == reflect.Interface || k == reflect.Struct {
		return t1.NumMethod() > t2.NumMethod()
	} else if k != reflect.Struct {
		return false
	}

	return true
}

SortByNumMethods is a builtin sorter to sort fields and values based on their type and its number of methods, highest number of methods goes first.

It is the default sorter on package-level struct injector function `Struct`.

type StructInjector

type StructInjector struct {

	// is true when contains bindable fields and it's a valid target struct,
	// it maybe 0 but struct may contain unexported fields or exported but no bindable (Stateless)
	// see `setState`.
	Has       bool
	CanInject bool // if any bindable fields when the state is NOT singleton.
	Scope     Scope

	FallbackBinder FallbackBinder
	ErrorHandler   ErrorHandler
	// contains filtered or unexported fields
}

StructInjector keeps the data that are needed in order to do the binding injection as fast as possible and with the best possible and safest way.

func MakeStructInjector

func MakeStructInjector(v reflect.Value, sorter Sorter, values ...reflect.Value) *StructInjector

MakeStructInjector returns a new struct injector, which will be the object that the caller should use to bind exported fields or embedded unexported fields that contain exported fields of the "v" struct value or pointer.

The hijack and the goodFunc are optional, the "values" is the dependencies collection.

func Struct

func Struct(s interface{}, values ...reflect.Value) *StructInjector

Struct is being used to return a new injector based on a struct value instance, if it contains fields that the types of those are matching with one or more of the `Values` then they are binded with the injector's `Inject` and `InjectElem` methods.

func (*StructInjector) Acquire

func (s *StructInjector) Acquire() reflect.Value

Acquire returns a new value of the struct or the same struct that is used for resolving the dependencies. If the scope is marked as singleton then it returns the first instance, otherwise it creates new and returns it.

See `Singleton` and `Stateless` for more.

func (*StructInjector) AcquireSlice

func (s *StructInjector) AcquireSlice() []reflect.Value

AcquireSlice same as `Acquire` but it returns a slice of values structs, this can be used when a struct is passed as an input parameter on a function, again if singleton then it returns a pre-created slice which contains the first struct value given by the struct injector's user.

func (*StructInjector) Inject

func (s *StructInjector) Inject(ctx context.Context, dest interface{})

Inject accepts a destination struct and any optional context value(s), hero and mvc takes only one context value and this is the `context.Context`. It applies the bindings to the "dest" struct. It calls the InjectElem.

func (*StructInjector) InjectElem

func (s *StructInjector) InjectElem(ctx context.Context, destElem reflect.Value)

InjectElem same as `Inject` but accepts a reflect.Value and bind the necessary fields directly.

func (*StructInjector) String

func (s *StructInjector) String() (trace string)

String returns a debug trace message.

type Values

type Values []reflect.Value

Values is a shortcut of []reflect.Value, it makes easier to remove and add dependencies.

func NewValues

func NewValues() Values

NewValues returns new empty (dependencies) values.

func (*Values) Add

func (bv *Values) Add(values ...interface{})

Add adds values as dependencies, if the struct's fields or the function's input arguments needs them, they will be defined as bindings (at build-time) and they will be used (at serve-time).

func (*Values) AddOnce

func (bv *Values) AddOnce(value interface{}) bool

AddOnce binds a value to the controller's field with the same type, if it's not binded already.

Returns false if binded already or the value is not the proper one for binding, otherwise true.

func (*Values) AddValues

func (bv *Values) AddValues(values ...reflect.Value)

AddValues same as `Add` but accepts reflect.Value dependencies instead of interface{} and appends them to the list if they pass some checks.

func (Values) Clone

func (bv Values) Clone() Values

Clone returns a copy of the current values.

func (Values) CloneWithFieldsOf

func (bv Values) CloneWithFieldsOf(s interface{}) Values

CloneWithFieldsOf will return a copy of the current values plus the "s" struct's fields that are filled(non-zero) by the caller.

func (Values) Has

func (bv Values) Has(value interface{}) bool

Has returns true if a binder responsible to bind and return a type of "typ" is already registered to this controller.

func (Values) Len

func (bv Values) Len() int

Len returns the length of the current "bv" values slice.

func (*Values) Remove

func (bv *Values) Remove(value interface{}, n int) bool

Remove unbinds a binding value based on the type, it returns true if at least one field is not binded anymore.

The "n" indicates the number of elements to remove, if <=0 then it's 1, this is useful because you may have bind more than one value to two or more fields with the same type.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL