di

package module
v0.3.5 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2023 License: MIT Imports: 12 Imported by: 2

README

gihub.com/csgura/di

Guice Style Dependency Injection Library for Golang

1.Binding

type AbstractModule interface {
	Configure(binder *Binder)
}

Implement the AbstractModule

1.1 Instance Bindings

If a module has no dependency with other modules

type BillingModule struct {
}
 
func (r *BillingModule) Configure ( binder *di.Binder ) {
    binder.BindSingleton((*TransactionLog)(nil), NewDBTransactionLog())

    // or you can use Guice style binding code
    binder.Bind((*TransactionLog)(nil)).ToInstance(NewDBTransactionLog());

}

1.2 Provider Bindings

If a module has dependencies with other modules

Singleton

 func (r *BillingModule) Configure ( binder *di.Binder ) {
    provider := func(injector di.Injector) interface {} {
        connection := injector.GetInstance((*Connection)(nil)).(Connection)
        ret := NewDatabaseTransactionLog(connection)
        return ret
    }
 
    binder.BindProvider((*TransactionLog)(nil), provider)

    // or you can use Guice style binding code
    binder.Bind((*TransactionLog)(nil)).ToProvider(provider);

}
Non singleton
binder.Bind((*TransactionLog)(nil)).ToProvider(provider).AsNonSingleton();
Eager singleton
binder.Bind((*TransactionLog)(nil)).ToProvider(provider).AsEagerSingleton();

1.3 Constructor Binding

// NewDatabaseTransactionLog is constructor func
func NewDatabaseTransactionLog( connection DatabaseConnection ) DatabaseTransactionLog
 
// bind TransactionLog to construct func
binder.Bind((*TransactionLog)(nil)).ToConstructor(NewDatabaseTransactionLog);


// above Bind code is equivalent to below code
binder.BindProvider((*TransactionLog)(nil),func(injector di.Injector) interface{} {
    return injector.InjectAndCall(NewDatabaseTransactionLog)
})

The Constructor function Should :

  • Not Use Variadic Argument
  • Returns Single return value
  • Returns Pointer for struct type

2. Module Listup

package modules
 
import (
    "github.com/csgura/di"
)
 
func GetImplements() *di.Implements {
    impls := di.NewImplements()
    impls.AddImplement("TestDB", &TestDBModule{})
    impls.AddImplement("ControllerActor", &N32ControllerActorModule{})
    impls.AddImplement("MemCache", &MemCacheModule{})
    impls.AddImplement("LogrusLogger", &LogrusModule{})
 
    return impls
}

3. Injector Creation

You can create injector using CreateInjector method with AbstractModule list

injector := di.CreateInjector(&BillingModule{}, &OhterModule{})

Or you can create an Injector from implmentations with enabled module slice

cfg := hocon.New("application.conf")

// enabeld is []string type and it is list of name of modules should be configured
enabled := cfg.GetStringArray("modules")
 
impls := di.NewImplements()

// these are named module
impls.AddImplement("BillingModule", &BillingModule{})
impls.AddImplement("OtherModule", &OtherModule{}) 

// this is anonymous module. always configured
impls.AddBind(func(binder *di.Binder) {
    binder.BindSingleton((*Config)(nil), cfg)
})

injector := impls.NewInjector(enabled)

Note : Config and hocon is not part of this Library

application.conf looks like this

modules = [
    "BillingModule",
]

4. Get Instance

log := injector.GetInstance((*TransactionLog)(nil)).(TransactionLog)

5. Iteration of Singletons

If you want to call Close() function of every singleton object that implements io.Closer and created by injector

list := injector.GetInstancesOf((*io.Closer)(nil))

for _, ins := range list {
	c := ins.(io.Closer)
	c.Close()
}

6. Comparison with Guice

6.1 Instance Bindings

Guice
public class BillingModule extends AbstractModule {
  protected void configure() {
    bind(TransactionLog.class).toInstance(new DatabaseTransactionLog());
  }
}
di package
func (r *BillingModule) Configure ( binder *di.Binder ) {
    binder.Bind((*TransactionLog)(nil)).ToInstance(NewDBTransactionLog());    
}

6.2 Linked Bindings

Guice
public class BillingModule extends AbstractModule {
  protected void configure() {
    
    bind(TransactionLog.class).to(DatabaseTransactionLog.class).in(Singleton.class);
  }
}
di package

Not Supported. Use Provider Binding or Constructor Binding

6.3 Provider Bindings

Guice
public class DatabaseTransactionLogProvider 
    implements Provider<TransactionLog> {
  private final Connection connection;
 
  @Inject
  public DatabaseTransactionLogProvider(Connection connection) {
    this.connection = connection;
  }
 
  
  public TransactionLog get() {
    DatabaseTransactionLog transactionLog = 
        new DatabaseTransactionLog(connection);
    return transactionLog;
  }
}
 
public class BillingModule extends AbstractModule {
  @Override
  protected void configure() {
    bind(TransactionLog.class).toProvider(DatabaseTransactionLogProvider.class);
  }
di package
func (r *BillingModule) Configure ( binder *di.Binder ) {
    provider := func(injector di.Injector) interface {} {
        connection := injector.GetInstance((*Connection)(nil)).(Connection)
        ret := NewDatabaseTransactionLog(connection)
        return ret
    }

    binder.Bind((*TransactionLog)(nil)).ToProvider(provider);
}

6.4 Constructor Bindings

Guice
bind(TransactionLog.class)
    .toConstructor(
       DatabaseTransactionLog.class
        .getConstructor(DatabaseConnection.class)
    );
di package
func NewDatabaseTransactionLog( connection DatabaseConnection ) DatabaseTransactionLog
 
binder.Bind((*TransactionLog)(nil)).ToConstructor(NewDatabaseTransactionLog);

6.5 Binding Scope

Guice
  • Singleton
bind(TransactionLog.class).to(DatabaseTransactionLog.class).in(Singleton.class);
  • Eager singleton
bind(TransactionLog.class).to(InMemoryTransactionLog.class).asEagerSingleton();
  • Non singleton ( default )
bind(TransactionLog.class).to(InMemoryTransactionLog.class)
di package
  • Singleton ( default )
binder.Bind((*TransactionLog)(nil)).ToProvider(provider);
  • Eager singleton
binder.Bind((*TransactionLog)(nil)).ToProvider(provider).AsEagerSingleton();
  • Non singleton ( not default )
binder.Bind((*TransactionLog)(nil)).ToProvider(provider).AsNonSingleton();

6.6 Injector Creation

Guice
Injector injector = Guice.createInjector(new BillingModule(), new OtherModule(), ... ); 
di package
injector := di.CreateInjector(&BillingModule{}, &OhterModule{})

6.7 Iteration of Bindings

Guice
injector.getBindings.forEach((key, value) => {
    if (Scopes.isSingleton(value)) {
      val obj = value.getProvider.get()
      obj match {
        case a: Closeable =>
          a.close()
        case _ =>
      }
    }
  })

sorry. it is scala code

di package

getBindings method not available, but GetInstancesOf method is available to iterate all singleton which assignable to the type

list := injector.GetInstancesOf((*io.Closer)(nil))
for _, ins := range list {
    c := ins.(io.Closer)
    c.Close()
}

6.8 Inject Members

Guice
class SomeClass {
    @Inject var config : Config = _
}
 
val objref = new SomeClass()
injector.injectMembers( objref )
di package

use di:"inject" tag to inject member

type SomeClass struct {
    config     Config   `di:"inject"`
}
 
obj := SomeClass{}
 
injector.InjectMembers(&obj)

6.9 Binding Annotations

Guice
bind(CreditCardProcessor.class)
        .annotatedWith(PayPal.class)
        .to(PayPalCreditCardProcessor.class);
 
bind(CreditCardProcessor.class)
        .annotatedWith(Names.named("Checkout"))
        .to(CheckoutCreditCardProcessor.class);
di package

Not Supported. Use type definition

type CreditCardProcessor interface {}
 
type PayPal CreditCardProcessor
type Checkout CreditCardProcessor
 
binder.Bind((*PayPal)(nil)).ToProvider(NewPayPalCreditCardProcessor);
binder.Bind((*Checkout)(nil)).ToProvider(NewCheckoutCreditCardProcessor);
 

payPal := injector.GetInstance((*PayPal)(nil)).(CreditCardProcessor)

6.10 Untargetted Bindings

Guice
bind(MyConcreteClass.class);
bind(AnotherConcreteClass.class).in(Singleton.class);
di package

Not Supported. Use Instance Binding or Provider Binding

binder.Bind((*MyConcreteClass)(nil).ToInstance(&MyConcreteClass{})

6.11 Just-In-Time Binding ( aka JIT Binding or implicit Binding )

di package

Not Supported

6.12 Module Combine

Guice
Module combined
     = Modules.combine(new ProductionModule(), new TestModule());
di package
combined := di.CombineModule(&ProductionModule{}, &TestModule{})

6.13 Module Override

Guice
Module functionalTestModule
     = Modules.override(new ProductionModule()).with(new TestModule());
di package
functionalTestModule := di.OverrideModule(&ProductionModule{}).With(&TestModule{})

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddDecoratorOf added in v0.3.3

func AddDecoratorOf[T any](binder *Binder, fn func(injector Injector))

func BindInterceptor added in v0.3.3

func BindInterceptor[T any](binder *Binder, fn func(inj Injector, value T) T)

func GetInstance added in v0.3.3

func GetInstance[T any](injector Injector) T

func GetInstanceOpt added in v0.3.3

func GetInstanceOpt[T any](injector Injector) fp.Option[T]

func GetInstancesOf added in v0.3.3

func GetInstancesOf[T any](injector Injector) []T

func TypeOf added in v0.3.3

func TypeOf[T any]() interface{}

Types

type AbstractModule

type AbstractModule interface {
	Configure(binder *Binder)
}

AbstractModule is used to create bindings

func CombineModule added in v0.2.6

func CombineModule(modules ...AbstractModule) AbstractModule

CombineModule Returns a new module that installs all of modules

type BindFunc added in v0.2.4

type BindFunc func(binder *Binder)

BindFunc can act as AbstractModule

func (BindFunc) Configure added in v0.2.4

func (bf BindFunc) Configure(binder *Binder)

Configure is implements of AbstractModule

type Binder

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

Binder has bindings

func (*Binder) AddDecoratorOf added in v0.2.7

func (b *Binder) AddDecoratorOf(ptrToType interface{}, decorator func(ij Injector))

AddDecoratorOf add customizing function which will be applied to the created singleton instance if the type is not singleton, then the decorator callback will not be called

func (*Binder) Bind added in v0.2.4

func (b *Binder) Bind(ptrToType interface{}) *Binding

Bind returns Binding that it is not binded anything

func (*Binder) BindConstructor added in v0.2.5

func (b *Binder) BindConstructor(ptrToType interface{}, constructor interface{}) *Binding

BindConstructor binds intf type to constructor function

func (*Binder) BindInterceptor added in v0.3.0

func (b *Binder) BindInterceptor(
	ptrToType interface{},
	interceptorProvider func(injector Injector, instance interface{}) interface{},
)

BindInterceptor binds interceptor

func (*Binder) BindProvider

func (b *Binder) BindProvider(ptrToType interface{}, provider func(injector Injector) interface{}) *Binding

BindProvider binds intf type to provider function

func (*Binder) BindSingleton

func (b *Binder) BindSingleton(ptrToType interface{}, instance interface{}) *Binding

BindSingleton binds intf type to singleton instance

func (*Binder) IfNotBinded added in v0.2.4

func (b *Binder) IfNotBinded(ptrToType interface{}) *Binding

IfNotBinded returns Binding that will used if there are no other binding for tpe type

type Binding added in v0.1.3

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

Binding has provider function and created singlton instances and it has some configurtions about binding

func BindConstructor added in v0.3.3

func BindConstructor[T any](binder *Binder, constructor interface{}) *Binding

func BindProvider added in v0.3.3

func BindProvider[T any](binder *Binder, fn func(inj Injector) T) *Binding

func BindSingleton added in v0.3.3

func BindSingleton[T any](binder *Binder, singleton T) *Binding

func (*Binding) AsEagerSingleton added in v0.1.3

func (b *Binding) AsEagerSingleton() *Binding

AsEagerSingleton set binding as eager singleton

func (*Binding) AsNonSingleton added in v0.1.5

func (b *Binding) AsNonSingleton() *Binding

AsNonSingleton set binding as non singleton

func (*Binding) ShouldCreateBefore added in v0.2.4

func (b *Binding) ShouldCreateBefore(ptrToType interface{}) *Binding

ShouldCreateBefore set creating order. this creation of instance should be performed before instance creation of the tpe type

func (*Binding) ToConstructor added in v0.2.5

func (b *Binding) ToConstructor(function interface{}) *Binding

ToConstructor binds type to the constructor

func (*Binding) ToInstance added in v0.2.4

func (b *Binding) ToInstance(instance interface{}) *Binding

ToInstance binds type to singleton instance

func (*Binding) ToProvider added in v0.2.4

func (b *Binding) ToProvider(provider func(injector Injector) interface{}) *Binding

ToProvider binds type to the provider

type BindingTP added in v0.3.3

type BindingTP[T any] struct {
	// contains filtered or unexported fields
}

func Bind added in v0.3.3

func Bind[T any](binder *Binder) BindingTP[T]

func IfNotBinded added in v0.3.3

func IfNotBinded[T any](binder *Binder) BindingTP[T]

func (BindingTP[T]) AsEagerSingleton added in v0.3.3

func (b BindingTP[T]) AsEagerSingleton() BindingTP[T]

func (BindingTP[T]) ShouldCreateBefore added in v0.3.3

func (b BindingTP[T]) ShouldCreateBefore(tpe interface{}) BindingTP[T]

func (BindingTP[T]) ToConstructor added in v0.3.3

func (b BindingTP[T]) ToConstructor(constructor interface{}) BindingTP[T]

func (BindingTP[T]) ToInstance added in v0.3.3

func (b BindingTP[T]) ToInstance(singleton T) BindingTP[T]

func (BindingTP[T]) ToProvider added in v0.3.3

func (b BindingTP[T]) ToProvider(provider func(injector Injector) T) BindingTP[T]

type Implements

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

Implements is registry of AbstractModule

func NewImplements

func NewImplements() *Implements

NewImplements returns new empty Implements

func (*Implements) AddBind added in v0.1.4

func (r *Implements) AddBind(bindF func(binder *Binder)) *Implements

AddBind adds no named abstrace module

func (*Implements) AddImplement

func (r *Implements) AddImplement(name string, impl AbstractModule) *Implements

AddImplement adds named abstract module to Implements

func (*Implements) AddImplements added in v0.1.9

func (r *Implements) AddImplements(impl *Implements) *Implements

AddImplements adds all named AbstraceModule of impl to this

func (*Implements) Clone added in v0.2.3

func (r *Implements) Clone() *Implements

Clone returns clone of this

func (*Implements) GetImplement added in v0.2.7

func (r *Implements) GetImplement(name string) AbstractModule

GetImplement returns AbstractModule

func (*Implements) HasImplement added in v0.2.3

func (r *Implements) HasImplement(name string) bool

HasImplement returns whether named module is registered

func (*Implements) NewInjector added in v0.2.6

func (r *Implements) NewInjector(moduleNames []string) Injector

NewInjector returns new Injector from implements with enabled modulenames

func (*Implements) NewInjectorWithTimeout added in v0.2.6

func (r *Implements) NewInjectorWithTimeout(moduleNames []string, timeout time.Duration) Injector

NewInjectorWithTimeout returns new Injector from implements with enabled modulenames and it checks timeout

func (*Implements) NewInjectorWithTrace added in v0.2.9

func (r *Implements) NewInjectorWithTrace(moduleNames []string, traceCallback TraceCallback) Injector

NewInjectorWithTrace creates injector and call callback function when instances are created

type Injector

type Injector interface {
	GetInstance(ptrToType interface{}) interface{}
	GetProperty(propName string) string
	SetProperty(propName string, value string)

	GetInstancesOf(ptrToType interface{}) []interface{}
	InjectMembers(ptrToStruct interface{})
	InjectAndCall(function interface{}) interface{}
	InjectValue(ptrToInterface interface{})
}

Injector used to get instance

func CreateInjector added in v0.2.6

func CreateInjector(modules ...AbstractModule) Injector

CreateInjector creates new Injector with provided modules

func NewInjector

func NewInjector(implements *Implements, moduleNames []string) Injector

NewInjector returns new Injector from implements with enabled modulenames

func NewInjectorWithTimeout added in v0.1.9

func NewInjectorWithTimeout(implements *Implements, moduleNames []string, timeout time.Duration) Injector

NewInjectorWithTimeout returns new Injector from implements with enabled modulenames and it checks timeout

type OverridableModule added in v0.2.6

type OverridableModule interface {
	AbstractModule
	With(overrides ...AbstractModule) AbstractModule
}

OverridableModule is overridable module

func OverrideModule added in v0.2.6

func OverrideModule(modules ...AbstractModule) OverridableModule

OverrideModule Returns a builder that creates a module that overlays override modules over the given modules.

type TraceCallback added in v0.2.9

type TraceCallback func(info *TraceInfo)

TraceCallback is trace call back function

type TraceInfo added in v0.2.9

type TraceInfo struct {
	TraceType        TraceType
	RequestedType    reflect.Type
	Referer          reflect.Type
	ReturnedInstance interface{}
	IsCreatedNow     bool
	ElapsedTime      time.Duration
	IsSingleton      bool
	IsBinded         bool
	IsEager          bool
}

TraceInfo is trace message

func (*TraceInfo) String added in v0.2.9

func (r *TraceInfo) String() string

type TraceType added in v0.2.9

type TraceType int

TraceType is trace event type

const (
	// InstanceRequest is trace event
	InstanceRequest TraceType = iota

	// InstanceWillBeCreated is trace event
	InstanceWillBeCreated

	// InstanceCreated is trace event
	InstanceCreated

	// InstanceReturned is trace event
	InstanceReturned
)

func (TraceType) String added in v0.2.9

func (r TraceType) String() string

Jump to

Keyboard shortcuts

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