dependencyinjection

package module
v0.0.0-...-3181626 Latest Latest
Warning

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

Go to latest
Published: Apr 5, 2024 License: Apache-2.0 Imports: 6 Imported by: 0

README

dependencyinjection

A simple dependency injection library using Golang generics

Usage

The library has two main concepts, Container and Provider.

A Container is the object that stores all the dependencies, a global container is provided dependencyinjection.Global.

A Provider provides a dependency, there are currently three implemented Provided types, Singleton, Factory and Value:

  • Singleton - Constructor will only be called once, result is used for all subsequent dependency resolutions.
  • Factory - Constructor is run every time the dependency is resolved.
  • Value - The static provided value is returned when the dependency is resolved.

Custom Provider types can be used also, by implementing the Provider interface. This could allow for more complex strategies.

Example

In this simple example a type Config is added to the global container. This an then later be resolved by objects that require it using dependencyinjection.Get[Config](ctx, dependencyinjection.Global).

func init() {
    // Register Config into the dependency injection container, in this example it loads the config from the filesystem.
    dependencyinjection.MustRegisterSingleton(dependencyinjection.Global, func(ctx context.Context, container *dependencyinjection.Container) (Config, error) {
        // Get filesystem, this allows different implementations to be provided. In reality for config files the real
        // filesystem will be the one used 99% of the time, but this illustrates how to get dependencies.
        //
        // An example of how the fs.FS object could have been added to the container is as follows:
        //  dependencyinjection.MustRegisterValue(dependencyinjection.Global, os.DirFS("/some/path"))
        //
        filesystem, err := dependencyinjection.Get[fs.FS](ctx, container)
        if err != nil {
            return Config{}, err
        }

        // Load the config
        file, err := filesystem.Open("config.json")
        if err != nil {
            return Config{}, err
        }

        // Ensure file gets closed
        defer file.Close()

        // Parse the config from a file
        var config Config
        if err := json.NewDecoder(file).Decode(&config); err != nil {
            return Config{}, err
        }

        // Return loaded config
        return config, nil
    })
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Global = &Container{}

Global is the default global dependency container

Functions

func Get

func Get[T any](ctx context.Context, container *Container) (T, error)

Get retrieves an object from the container, constructing it if necessary

func Inject

func Inject[T any](ctx context.Context, container *Container, into *T) (err error)

Inject gets a dependency into a pointer receiver

func IsDependencyAlreadyRegistered

func IsDependencyAlreadyRegistered(err error) bool

IsDependencyAlreadyRegistered returns true if the error is a ErrDependencyAlreadyRegistered

func IsDependencyCycle

func IsDependencyCycle(err error) bool

IsDependencyCycle returns true if the error is a ErrDependencyCycle

func IsDependencyNotRegistered

func IsDependencyNotRegistered(err error) bool

IsDependencyNotRegistered returns true if the error is a ErrDependencyNotRegistered

func IsNilReceiver

func IsNilReceiver(err error) bool

IsNilReceiver returns true if the error is a ErrNilReceiver

func MustRegister

func MustRegister[T any](container *Container, provider Provider[T])

MustRegister registers a new value provider in the dependency injection container. The method panics on error.

func MustRegisterFactory

func MustRegisterFactory[T any](container *Container, fn Constructor[T])

MustRegisterFactory adds a factory to the dependency injection container. The method panics on error.

func MustRegisterSingleton

func MustRegisterSingleton[T any](container *Container, fn Constructor[T])

MustRegisterSingleton adds a singleton to the dependency injection container. The method panics on error.

func MustRegisterValue

func MustRegisterValue[T any](container *Container, value T)

MustRegisterValue adds a value to the dependency injection container. The method panics on error.

func Register

func Register[T any](container *Container, provider Provider[T]) error

Register registers a new value provider in the dependency injection container.

func RegisterFactory

func RegisterFactory[T any](container *Container, fn Constructor[T]) error

RegisterFactory adds a factory to the dependency injection container. It is equivalent to calling `Register(ctx, container, NewFactoryProvider(fn))`

func RegisterSingleton

func RegisterSingleton[T any](container *Container, fn Constructor[T]) error

RegisterSingleton adds a singleton to the dependency injection container. It is equivalent to calling `Register(ctx, container, NewSingletonProvider(fn))`

func RegisterValue

func RegisterValue[T any](container *Container, value T) error

RegisterValue adds a value to the dependency injection container. It is equivalent to calling `Register(ctx, container, NewValueProvider(value))`

Types

type Constructor

type Constructor[T any] func(context.Context, *Container) (T, error)

Constructor creates a new instance of an object

type Container

type Container struct {
	// contains filtered or unexported fields
}

Container holds all dependencies, resolving them as required

type ErrDependencyAlreadyRegistered

type ErrDependencyAlreadyRegistered struct {
	// contains filtered or unexported fields
}

ErrDependencyAlreadyRegistered is the type of error returned when type that is already registered with a container is re-registered.

func (ErrDependencyAlreadyRegistered) Error

type ErrDependencyCycle

type ErrDependencyCycle struct {
	// contains filtered or unexported fields
}

ErrDependencyAlreadyRegistered is the type of error returned when dependency cycle is detected when constructing dependencies

func (ErrDependencyCycle) Error

func (e ErrDependencyCycle) Error() string

type ErrDependencyNotRegistered

type ErrDependencyNotRegistered struct {
	// contains filtered or unexported fields
}

ErrDependencyNotRegistered is the type of error returned when a requested type is not registered with the container

func (ErrDependencyNotRegistered) Error

type ErrNilReceiver

type ErrNilReceiver struct{}

ErrNilReceiver is the type of error returned when a nil receiver is used in the Inject method

func (ErrNilReceiver) Error

func (e ErrNilReceiver) Error() string

type Provider

type Provider[T any] interface {
	Resolve(context.Context, *Container) (T, error)
}

Provider provides a value of a given type.

func NewFactoryProvider

func NewFactoryProvider[T any](fn Constructor[T]) Provider[T]

NewFactoryProvider returns a provider that calls the provided constructor to generate the value every time is is required.

func NewSingletonProvider

func NewSingletonProvider[T any](fn Constructor[T]) Provider[T]

NewSingletonProvider returns a provider that calls the provided constructor once to generate the value and provides the same value on subsequent resolves. The provider is thread safe.

func NewValueProvider

func NewValueProvider[T any](value T) Provider[T]

NewValueProvider returns a provider that will always return the given value. This allows objects to be directly added to the Container without needing a constructor.

Jump to

Keyboard shortcuts

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