...

Source file src/github.com/codegangsta/inject/inject.go

Documentation: github.com/codegangsta/inject

     1  // Package inject provides utilities for mapping and injecting dependencies in various ways.
     2  package inject
     3  
     4  import (
     5  	"fmt"
     6  	"reflect"
     7  )
     8  
     9  // Injector represents an interface for mapping and injecting dependencies into structs
    10  // and function arguments.
    11  type Injector interface {
    12  	Applicator
    13  	Invoker
    14  	TypeMapper
    15  	// SetParent sets the parent of the injector. If the injector cannot find a
    16  	// dependency in its Type map it will check its parent before returning an
    17  	// error.
    18  	SetParent(Injector)
    19  }
    20  
    21  // Applicator represents an interface for mapping dependencies to a struct.
    22  type Applicator interface {
    23  	// Maps dependencies in the Type map to each field in the struct
    24  	// that is tagged with 'inject'. Returns an error if the injection
    25  	// fails.
    26  	Apply(interface{}) error
    27  }
    28  
    29  // Invoker represents an interface for calling functions via reflection.
    30  type Invoker interface {
    31  	// Invoke attempts to call the interface{} provided as a function,
    32  	// providing dependencies for function arguments based on Type. Returns
    33  	// a slice of reflect.Value representing the returned values of the function.
    34  	// Returns an error if the injection fails.
    35  	Invoke(interface{}) ([]reflect.Value, error)
    36  }
    37  
    38  // TypeMapper represents an interface for mapping interface{} values based on type.
    39  type TypeMapper interface {
    40  	// Maps the interface{} value based on its immediate type from reflect.TypeOf.
    41  	Map(interface{}) TypeMapper
    42  	// Maps the interface{} value based on the pointer of an Interface provided.
    43  	// This is really only useful for mapping a value as an interface, as interfaces
    44  	// cannot at this time be referenced directly without a pointer.
    45  	MapTo(interface{}, interface{}) TypeMapper
    46  	// Provides a possibility to directly insert a mapping based on type and value.
    47  	// This makes it possible to directly map type arguments not possible to instantiate
    48  	// with reflect like unidirectional channels.
    49  	Set(reflect.Type, reflect.Value) TypeMapper
    50  	// Returns the Value that is mapped to the current type. Returns a zeroed Value if
    51  	// the Type has not been mapped.
    52  	Get(reflect.Type) reflect.Value
    53  }
    54  
    55  type injector struct {
    56  	values map[reflect.Type]reflect.Value
    57  	parent Injector
    58  }
    59  
    60  // InterfaceOf dereferences a pointer to an Interface type.
    61  // It panics if value is not an pointer to an interface.
    62  func InterfaceOf(value interface{}) reflect.Type {
    63  	t := reflect.TypeOf(value)
    64  
    65  	for t.Kind() == reflect.Ptr {
    66  		t = t.Elem()
    67  	}
    68  
    69  	if t.Kind() != reflect.Interface {
    70  		panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")
    71  	}
    72  
    73  	return t
    74  }
    75  
    76  // New returns a new Injector.
    77  func New() Injector {
    78  	return &injector{
    79  		values: make(map[reflect.Type]reflect.Value),
    80  	}
    81  }
    82  
    83  // Invoke attempts to call the interface{} provided as a function,
    84  // providing dependencies for function arguments based on Type.
    85  // Returns a slice of reflect.Value representing the returned values of the function.
    86  // Returns an error if the injection fails.
    87  // It panics if f is not a function
    88  func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
    89  	t := reflect.TypeOf(f)
    90  
    91  	var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
    92  	for i := 0; i < t.NumIn(); i++ {
    93  		argType := t.In(i)
    94  		val := inj.Get(argType)
    95  		if !val.IsValid() {
    96  			return nil, fmt.Errorf("Value not found for type %v", argType)
    97  		}
    98  
    99  		in[i] = val
   100  	}
   101  
   102  	return reflect.ValueOf(f).Call(in), nil
   103  }
   104  
   105  // Maps dependencies in the Type map to each field in the struct
   106  // that is tagged with 'inject'.
   107  // Returns an error if the injection fails.
   108  func (inj *injector) Apply(val interface{}) error {
   109  	v := reflect.ValueOf(val)
   110  
   111  	for v.Kind() == reflect.Ptr {
   112  		v = v.Elem()
   113  	}
   114  
   115  	if v.Kind() != reflect.Struct {
   116  		return nil // Should not panic here ?
   117  	}
   118  
   119  	t := v.Type()
   120  
   121  	for i := 0; i < v.NumField(); i++ {
   122  		f := v.Field(i)
   123  		structField := t.Field(i)
   124  		if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") {
   125  			ft := f.Type()
   126  			v := inj.Get(ft)
   127  			if !v.IsValid() {
   128  				return fmt.Errorf("Value not found for type %v", ft)
   129  			}
   130  
   131  			f.Set(v)
   132  		}
   133  
   134  	}
   135  
   136  	return nil
   137  }
   138  
   139  // Maps the concrete value of val to its dynamic type using reflect.TypeOf,
   140  // It returns the TypeMapper registered in.
   141  func (i *injector) Map(val interface{}) TypeMapper {
   142  	i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)
   143  	return i
   144  }
   145  
   146  func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {
   147  	i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)
   148  	return i
   149  }
   150  
   151  // Maps the given reflect.Type to the given reflect.Value and returns
   152  // the Typemapper the mapping has been registered in.
   153  func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {
   154  	i.values[typ] = val
   155  	return i
   156  }
   157  
   158  func (i *injector) Get(t reflect.Type) reflect.Value {
   159  	val := i.values[t]
   160  
   161  	if val.IsValid() {
   162  		return val
   163  	}
   164  
   165  	// no concrete types found, try to find implementors
   166  	// if t is an interface
   167  	if t.Kind() == reflect.Interface {
   168  		for k, v := range i.values {
   169  			if k.Implements(t) {
   170  				val = v
   171  				break
   172  			}
   173  		}
   174  	}
   175  
   176  	// Still no type found, try to look it up on the parent
   177  	if !val.IsValid() && i.parent != nil {
   178  		val = i.parent.Get(t)
   179  	}
   180  
   181  	return val
   182  
   183  }
   184  
   185  func (i *injector) SetParent(parent Injector) {
   186  	i.parent = parent
   187  }
   188  

View as plain text