di

package module
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Apr 17, 2024 License: MIT Imports: 9 Imported by: 108

README

fluffy-dozm-di

This is a new project based on dozm/di. The main reason for the deviation is addition of features that do not exist in the original.

Features

The features added are;

The ability to add an object that implements many interfaces.

I would like to add an object that MAY implement a lot of interfaces, but in this case I want to only register a subset of them. You may have an object that you would like to new with different inputs and more importantly cherry pick which interfaces get registered in the DI. You may not want to register the object itself, but only the Interface. I couldn't do this with the original dozm/di and even with asp.net's di on which dozm/di was based on.

The ability to register by an lookup key and fetch by the lookup key

I would like to register an object by a name. i.e. "my-awesome-object".

A dependency injection module based on reflection.

Installation

go get -u github.com/fluffy-bunny/fluffy-dozm-di

Quick start

package main

import (
    "fmt"
    di "github.com/fluffy-bunny/fluffy-dozm-di"
)

func main() {
    // Create a ContainerBuilder
    b := di.Builder()
    
    // Register some services with generic helper function.
    di.AddSingleton[string](b, func() string { return "hello" })
    di.AddTransient[int](b, func() int { return 1 })
    di.AddScoped[int](b, func() int { return 2 })

    // Build the container
    c := b.Build()

    // Usually, you should not resolve a service directly from the root scope.
    // So, get the di.ScopeFactory (it's a built-in service) to create a scope.
    // Typically, in web application we create a scope for per HTTP request.
    scopeFactory := di.Get[di.ScopeFactory](c)
    scope := scopeFactory.CreateScope()
    c = scope.Container()

    // Get a service from the container
    s := di.Get[string](c)
    fmt.Println(s)

    // Get all of the services with the type int as a slice.
    intSlice := di.Get[[]int](c)
    fmt.Println(intSlice)
}

Documentation

Index

Constants

View Source
const DefaultSlot int = 0
View Source
const Version = "v0.1.0"

Variables

View Source
var ContainerImplType = reflectx.TypeOf[container]()
View Source
var ContainerType = reflectx.TypeOf[Container]()
View Source
var EmptyServiceCacheKey = ServiceCacheKey{nil, 0}
View Source
var IsServiceType = reflectx.TypeOf[IsService]()
View Source
var NoneResultCache = newResultCache(CacheLocation_None, EmptyServiceCacheKey)
View Source
var ScopeFactoryType = reflectx.TypeOf[ScopeFactory]()

Functions

func AddFunc added in v0.0.3

func AddFunc[T any](cb ContainerBuilder, ctor any)

AddFunc is a convenience method to add a singleton service descriptor to the ContainerBuilder.

func AddFuncWithLookupKeys added in v0.0.3

func AddFuncWithLookupKeys[T any](cb ContainerBuilder,
	ctor any,
	lookupKeys []string,
	metadata map[string]interface{},
)

AddFuncByLookupKey is a convenience method to add a singleton service descriptor to the ContainerBuilder.

func AddInstance

func AddInstance[T any](cb ContainerBuilder, instance any, implementedInterfaceTypes ...reflect.Type)

Add an instance service descriptor to the ContainerBuilder. T is the service type, cb is the ContainerBuilder, the instance must be assignable to the service T.

func AddInstanceWithLookupKeys

func AddInstanceWithLookupKeys[T any](cb ContainerBuilder,
	instance any,
	lookupKeys []string,
	metadata map[string]interface{},
	implementedInterfaceTypes ...reflect.Type)

Add an instance service descriptor to the ContainerBuilder. T is the service type, cb is the ContainerBuilder, the instance must be assignable to the service T. lookupKeys is the lookup keys of the service T. implementedInterfaceTypes is the implemented interface types of the service T.

func AddScoped

func AddScoped[T any](cb ContainerBuilder, ctor any, implementedInterfaceTypes ...reflect.Type)

Add a scoped service descriptor to the ContainerBuilder. T is the service type, cb is the ContainerBuilder, ctor is the constructor of the service T. implementedInterfaceTypes is the implemented interface types of the service T.

func AddScopedFactory

func AddScopedFactory[T any](cb ContainerBuilder, factory Factory)

func AddScopedWithLookupKeys

func AddScopedWithLookupKeys[T any](cb ContainerBuilder,
	ctor any,
	lookupKeys []string,
	metadata map[string]interface{},
	implementedInterfaceTypes ...reflect.Type)

Add a scoped service descriptor to the ContainerBuilder. T is the service type, cb is the ContainerBuilder, ctor is the constructor of the service T. lookupKeys is the lookup keys of the service T. implementedInterfaceTypes is the implemented interface types of the service T.

func AddSingleton

func AddSingleton[T any](cb ContainerBuilder, ctor any, implementedInterfaceTypes ...reflect.Type)

Add a singleton service descriptor to the ContainerBuilder. T is the service type, cb is the ContainerBuilder, ctor is the constructor of the service T.

func AddSingletonFactory

func AddSingletonFactory[T any](cb ContainerBuilder, factory Factory)

func AddSingletonWithLookupKeys

func AddSingletonWithLookupKeys[T any](cb ContainerBuilder,
	ctor any,
	lookupKeys []string,
	metadata map[string]interface{},
	implementedInterfaceTypes ...reflect.Type)

Add a singleton service descriptor to the ContainerBuilder. T is the service type, cb is the ContainerBuilder, ctor is the constructor of the service T. lookupKeys is the lookup keys of the service T. implementedInterfaceTypes is the implemented interface types of the service T.

func AddTransient

func AddTransient[T any](cb ContainerBuilder, ctor any, implementedInterfaceTypes ...reflect.Type)

Add a transient service descriptor to the ContainerBuilder. T is the service type, cb is the ContainerBuilder, ctor is the constructor of the service T.

func AddTransientFactory

func AddTransientFactory[T any](cb ContainerBuilder, factory Factory)

func AddTransientWithLookupKeys

func AddTransientWithLookupKeys[T any](cb ContainerBuilder,
	ctor any,
	lookupKeys []string,
	metadata map[string]interface{},
	implementedInterfaceTypes ...reflect.Type)

Add a transient service descriptor to the ContainerBuilder. T is the service type, cb is the ContainerBuilder, ctor is the constructor of the service T. lookupKeys is the lookup keys of the service T. implementedInterfaceTypes is the implemented interface types of the service T.

func Get

func Get[T any](c Container) T

Get service of the type T from the container c

func GetByLookupKey

func GetByLookupKey[T any](c Container, key string) T

Get service of the type T from the container c

func Invoke

func Invoke(c Container, fn any) (fnReturn []any, err error)

Invoke the function fn. the input paramenters of the fn function will be resolved from the Container c.

func TryGet

func TryGet[T any](c Container) (result T, err error)

func TryGetByLookupKey

func TryGetByLookupKey[T any](c Container, key string) (result T, err error)

Types

type CacheLocation

type CacheLocation byte

callsite result cache location

const (
	CacheLocation_Root CacheLocation = iota
	CacheLocation_Scope
	CacheLocation_Dispose
	CacheLocation_None
)

type CallSite

type CallSite interface {
	ServiceType() reflect.Type
	Kind() CallSiteKind
	Value() any
	SetValue(any)
	Cache() ResultCache
}

type CallSiteFactory

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

func (*CallSiteFactory) Add

func (f *CallSiteFactory) Add(serviceType reflect.Type, callSite CallSite)

func (*CallSiteFactory) Descriptors

func (f *CallSiteFactory) Descriptors() []*Descriptor

func (*CallSiteFactory) GetCallSite

func (f *CallSiteFactory) GetCallSite(serviceType reflect.Type, chain *callSiteChain) (CallSite, error)

func (*CallSiteFactory) GetCallSiteByDescriptor

func (f *CallSiteFactory) GetCallSiteByDescriptor(descriptor *Descriptor, chain *callSiteChain) (CallSite, error)

func (*CallSiteFactory) IsService

func (f *CallSiteFactory) IsService(serviceType reflect.Type) bool

Determines if the specified service type is available from the ServiceProvider.

type CallSiteKind

type CallSiteKind byte
const (
	CallSiteKind_Factory CallSiteKind = iota
	CallSiteKind_Constructor
	CallSiteKind_Constant
	CallSiteKind_Slice
	CallSiteKind_Container
	CallSiteKind_Scope
	CallSiteKind_Transient
	CallSiteKind_Singleton
)

type CallSiteResolver

type CallSiteResolver struct {
	// contains filtered or unexported fields
}
var CallSiteResolverInstance *CallSiteResolver = newCallSiteResolver()

func (*CallSiteResolver) Resolve

func (r *CallSiteResolver) Resolve(callSite CallSite, scope *ContainerEngineScope) (any, error)

type CallSiteValidator

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

func (*CallSiteValidator) ValidateCallSite

func (v *CallSiteValidator) ValidateCallSite(callSite CallSite) error

func (*CallSiteValidator) ValidateResolution

func (v *CallSiteValidator) ValidateResolution(serviceType reflect.Type, scope Scope, rootScope Scope) (err error)

type ConstantCallSite

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

func (*ConstantCallSite) Cache

func (cs *ConstantCallSite) Cache() ResultCache

func (*ConstantCallSite) DefaultValue

func (cs *ConstantCallSite) DefaultValue() any

func (*ConstantCallSite) Kind

func (cs *ConstantCallSite) Kind() CallSiteKind

func (*ConstantCallSite) ServiceType

func (cs *ConstantCallSite) ServiceType() reflect.Type

func (*ConstantCallSite) SetValue

func (cs *ConstantCallSite) SetValue(v any)

func (*ConstantCallSite) Value

func (cs *ConstantCallSite) Value() any

type ConstructorCallSite

type ConstructorCallSite struct {
	Ctor       *ConstructorInfo
	Parameters []CallSite
	// contains filtered or unexported fields
}

func (*ConstructorCallSite) Cache

func (cs *ConstructorCallSite) Cache() ResultCache

func (*ConstructorCallSite) Kind

func (cs *ConstructorCallSite) Kind() CallSiteKind

func (*ConstructorCallSite) ServiceType

func (cs *ConstructorCallSite) ServiceType() reflect.Type

func (*ConstructorCallSite) SetValue

func (cs *ConstructorCallSite) SetValue(v any)

func (*ConstructorCallSite) Value

func (cs *ConstructorCallSite) Value() any

type ConstructorInfo

type ConstructorInfo struct {
	FuncType  reflect.Type
	FuncValue reflect.Value
	// input parameter types
	In []reflect.Type
	// output parameter types
	Out []reflect.Type
}

func (*ConstructorInfo) Call

func (c *ConstructorInfo) Call(params []reflect.Value) []reflect.Value

type Container

type Container interface {
	Get(reflect.Type) (any, error)
	GetDescriptors() []*Descriptor
	GetByLookupKey(reflect.Type, string) (any, error)
}

type ContainerBuilder

type ContainerBuilder interface {
	Add(...*Descriptor)
	// Remove all the descriptors that the service type is t.
	Remove(t reflect.Type)
	Contains(t reflect.Type) bool
	Build() Container
	ConfigureOptions(func(*Options))
}

func Builder

func Builder() ContainerBuilder

Create a ContainerBuilder

type ContainerCallSite

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

func (*ContainerCallSite) Cache

func (cs *ContainerCallSite) Cache() ResultCache

func (*ContainerCallSite) Kind

func (cs *ContainerCallSite) Kind() CallSiteKind

func (*ContainerCallSite) ServiceType

func (cs *ContainerCallSite) ServiceType() reflect.Type

func (*ContainerCallSite) SetValue

func (cs *ContainerCallSite) SetValue(v any)

func (*ContainerCallSite) Value

func (cs *ContainerCallSite) Value() any

type ContainerEngine

type ContainerEngine interface {
	RealizeService(CallSite) (ServiceAccessor, error)
}

type ContainerEngineScope

type ContainerEngineScope struct {
	RootContainer    *container
	IsRootScope      bool
	ResolvedServices map[ServiceCacheKey]any
	Locker           *sync.Mutex
	// contains filtered or unexported fields
}

func (*ContainerEngineScope) BeginDispose

func (s *ContainerEngineScope) BeginDispose() []Disposable

func (*ContainerEngineScope) CaptureDisposable

func (s *ContainerEngineScope) CaptureDisposable(service any) (Disposable, error)

func (*ContainerEngineScope) CaptureDisposableWithoutLock

func (s *ContainerEngineScope) CaptureDisposableWithoutLock(service any) (Disposable, error)

func (*ContainerEngineScope) Container

func (s *ContainerEngineScope) Container() Container

func (*ContainerEngineScope) CreateScope

func (s *ContainerEngineScope) CreateScope() Scope

func (*ContainerEngineScope) Disposables

func (s *ContainerEngineScope) Disposables() []Disposable

func (*ContainerEngineScope) Dispose

func (s *ContainerEngineScope) Dispose()

func (*ContainerEngineScope) Get

func (s *ContainerEngineScope) Get(serviceType reflect.Type) (any, error)

func (*ContainerEngineScope) GetByLookupKey

func (s *ContainerEngineScope) GetByLookupKey(serviceType reflect.Type, key string) (any, error)

func (*ContainerEngineScope) GetDescriptors

func (c *ContainerEngineScope) GetDescriptors() []*Descriptor

type Descriptor

type Descriptor struct {
	ServiceType               reflect.Type
	Lifetime                  Lifetime
	Ctor                      *ConstructorInfo
	Instance                  any
	Factory                   func(Container) any
	ImplementedInterfaceTypes []reflect.Type
	LookupKeys                []string
	Metadata                  map[string]interface{}
}

service descriptor

func Instance

func Instance[T any](instance any, implementedInterfaceTypes ...reflect.Type) *Descriptor

New a descriptor with instance

func NewConstructorDescriptor

func NewConstructorDescriptor(serviceType reflect.Type, lifetime Lifetime, ctor any, implementedInterfaceTypes ...reflect.Type) *Descriptor

func NewFactoryDescriptor

func NewFactoryDescriptor(serviceType reflect.Type, lifetime Lifetime, factory Factory) *Descriptor

func NewInstanceDescriptor

func NewInstanceDescriptor(serviceType reflect.Type, instance any, implementedInterfaceTypes ...reflect.Type) *Descriptor

func Scoped

func Scoped[T any](ctor any, implementedInterfaceTypes ...reflect.Type) *Descriptor

New a scoped constructor descriptor

func ScopedFactory

func ScopedFactory[T any](factory Factory) *Descriptor

New a scoped factory descriptor

func Singleton

func Singleton[T any](ctor any, implementedInterfaceTypes ...reflect.Type) *Descriptor

New a singleton constructor descriptor

func SingletonFactory

func SingletonFactory[T any](factory Factory) *Descriptor

New a singleton factory descriptor

func Transient

func Transient[T any](ctor any, implementedInterfaceTypes ...reflect.Type) *Descriptor

New a transient constructor descriptor

func TransientFactory

func TransientFactory[T any](factory Factory) *Descriptor

New a transient factory descriptor

func (*Descriptor) String

func (d *Descriptor) String() string

type Disposable

type Disposable interface {
	Dispose()
}

type Factory

type Factory func(Container) any

type FactoryCallSite

type FactoryCallSite struct {
	Factory Factory
	// contains filtered or unexported fields
}

Factory call site

func (*FactoryCallSite) Cache

func (cs *FactoryCallSite) Cache() ResultCache

func (*FactoryCallSite) Kind

func (cs *FactoryCallSite) Kind() CallSiteKind

func (*FactoryCallSite) ServiceType

func (cs *FactoryCallSite) ServiceType() reflect.Type

func (*FactoryCallSite) SetValue

func (cs *FactoryCallSite) SetValue(v any)

func (*FactoryCallSite) Value

func (cs *FactoryCallSite) Value() any

type IsService

type IsService interface {
	IsService(serviceType reflect.Type) bool
}

Optional service used to determine if the specified type is available from the Container.

type Lifetime

type Lifetime byte
const (
	Lifetime_Singleton Lifetime = iota
	Lifetime_Scoped
	Lifetime_Transient
)

type Options

type Options struct {
	ValidateScopes  bool
	ValidateOnBuild bool
}

Container options.

func DefaultOptions

func DefaultOptions() Options

Get default container options.

type ResultCache

type ResultCache struct {
	Location CacheLocation
	Key      ServiceCacheKey
}

callsite result cache

type Scope

type Scope interface {
	Container() Container
	Dispose()
}

type ScopeFactory

type ScopeFactory interface {
	CreateScope() Scope
}

type ServiceAccessor

type ServiceAccessor func(*ContainerEngineScope) (any, error)

type ServiceCacheKey

type ServiceCacheKey struct {
	// Type of service being cached
	ServiceType reflect.Type

	// Reverse index of the service when resolved in slice where default instance gets slot 0.
	Slot int
}

type SliceCallSite

type SliceCallSite struct {
	Elem      reflect.Type
	CallSites []CallSite
	// contains filtered or unexported fields
}

func (*SliceCallSite) Cache

func (cs *SliceCallSite) Cache() ResultCache

func (*SliceCallSite) Kind

func (cs *SliceCallSite) Kind() CallSiteKind

func (*SliceCallSite) ServiceType

func (cs *SliceCallSite) ServiceType() reflect.Type

func (*SliceCallSite) SetValue

func (cs *SliceCallSite) SetValue(v any)

func (*SliceCallSite) Value

func (cs *SliceCallSite) Value() any

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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