Git Product home page Git Product logo

inject's Introduction

inject

-- import "github.com/codegangsta/inject"

Package inject provides utilities for mapping and injecting dependencies in various ways.

Language Translations:

Usage

func InterfaceOf

func InterfaceOf(value interface{}) reflect.Type

InterfaceOf dereferences a pointer to an Interface type. It panics if value is not an pointer to an interface.

type Applicator

type Applicator interface {
	// Maps dependencies in the Type map to each field in the struct
	// that is tagged with 'inject'. Returns an error if the injection
	// fails.
	Apply(interface{}) error
}

Applicator represents an interface for mapping dependencies to a struct.

type Injector

type Injector interface {
	Applicator
	Invoker
	TypeMapper
	// SetParent sets the parent of the injector. If the injector cannot find a
	// dependency in its Type map it will check its parent before returning an
	// error.
	SetParent(Injector)
}

Injector represents an interface for mapping and injecting dependencies into structs and function arguments.

func New

func New() Injector

New returns a new Injector.

type Invoker

type Invoker interface {
	// Invoke attempts to call the interface{} provided as a function,
	// providing dependencies for function arguments based on Type. Returns
	// a slice of reflect.Value representing the returned values of the function.
	// Returns an error if the injection fails.
	Invoke(interface{}) ([]reflect.Value, error)
}

Invoker represents an interface for calling functions via reflection.

type TypeMapper

type TypeMapper interface {
	// Maps the interface{} value based on its immediate type from reflect.TypeOf.
	Map(interface{}) TypeMapper
	// Maps the interface{} value based on the pointer of an Interface provided.
	// This is really only useful for mapping a value as an interface, as interfaces
	// cannot at this time be referenced directly without a pointer.
	MapTo(interface{}, interface{}) TypeMapper
	// Provides a possibility to directly insert a mapping based on type and value.
	// This makes it possible to directly map type arguments not possible to instantiate
	// with reflect like unidirectional channels.
	Set(reflect.Type, reflect.Value) TypeMapper
	// Returns the Value that is mapped to the current type. Returns a zeroed Value if
	// the Type has not been mapped.
	Get(reflect.Type) reflect.Value
}

TypeMapper represents an interface for mapping interface{} values based on type.

inject's People

Contributors

beatrichartz avatar codegangsta avatar guillermooo avatar owenthereal avatar ssbunny avatar tarrsalah avatar thomaswilde avatar titanous avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

inject's Issues

Hide reflect.Value/Type from interfaces

When using Invoke() or Get() you have to do a lot of Interface() and type assertions. It may be useful to change some of the methods to use plain interfaces{}, similar to how encoding/json works.

I was thinking Get would look something like this:

func (i *injector) Get(dst interface{}) {
    dval := reflect.ValueOf(dst).Elem()
    val := i.values[dval.Type()]
    if val.IsValid() {
        dval.Set(val)
    } else if i.parent != nil {
        i.parent.Get(dst)
    }
}

func (i *injector) GetInterface(dst interface{}, ifacePtr interface{}) {
    val := i.values[InterfaceOf(ifacePtr)]
    if val.IsValid() {
        reflect.ValueOf(dst).Elem().Set(val)
    } else if i.parent != nil {
        i.parent.GetInterface(dst, ifacePtr)
    }
}

These functions would be used like this:

obj := Obj{}

i.Get(&obj)
// OR
i.GetInterface(&obj, (*MyInterface)(nil))

Verses this:

ov := i.Get(Obj{})
// OR
ov := i.Get(InterfaceOf((*MyInterface)(nil)))

obj = ov.Interface().(Obj)

You could probably optimize this further by doing reflect.ValueOf/TypeOf once in the public methods and pass those to private methods that understand reflect.Value/Type.

Invoke could return []interface{} instead of []reflect.Value.

i think parent of injector should be pointer

type Injector interface {
    Applicator
    Invoker
    TypeMapper
    // SetParent sets the parent of the injector. If the injector cannot find a
    // dependency in its Type map it will check its parent before returning an
    // error.
    SetParent(*Injector) // <-- we need reference to parent, not a copy of parent
}

what do you think?

Maybe it's better this way, rtype.hash used as map keys

my english is not good enough.

in package reflect

type rtype struct {
    size          uintptr        // size in bytes
    hash          uint32      // hash of type; avoids computation in hash tables
    _             uint8          // unused/padding
    align         uint8         // alignment of variable with this type
    fieldAlign    uint8       // alignment of struct field with this type
    kind          uint8         // enumeration for C
    alg           *uintptr      // algorithm table (../runtime/runtime.h:/Alg)
    gc            unsafe.Pointer // garbage collection data
    string        *string        // string form; unnecessary but undeniably useful
    *uncommonType                // (relatively) uncommon fields
    ptrToThis     *rtype         // type for pointer to this type, if used in binary or has methods
}
type emptyInterface struct {
    typ  *rtype
    word iword
}
func TypeOf(i interface{}) Type {
    eface := *(*emptyInterface)(unsafe.Pointer(&i))
    return toType(eface.typ)
}

Why not use this code for injector, and rtype.hash used as map keys?
uint32 used as map keys is faster more than reflect.Type.

Value not found for type *xxx.XXXType

x1.EventData = []interface{}{x1, []interface{}{portScan.TargetStr(task.ScanWeb)}}
G_Engine.EventData <- x1
------------------------------

for _, i := range ed.EventData {
				in.Map(i)
			}
			v, err := in.Invoke(fnCall)

now ,err:
Value not found for type *xxx.XXXType

about injector Get method

injector using a map stored values, use type in the Get method to obtain value. If there is more value will be lost if the same type value, for example there are two Int64 value. I was a novice, I'm not sure.

support the variadic function

Usage like this:

package main

import (
    "fmt"
    "github.com/codegangsta/inject"
)

type SliceInterface interface{}

func Handler1(s string, si ...SliceInterface) {
    fmt.Println("Handler1", s, si)
}

func Handler2(s string, si ...interface{}) {
    fmt.Println("Handler2", s, si)
}

func Handler3(s string, si ...int) {
    fmt.Println("Handler3", s, si)
}

func main() {
    s := "foo"
    si := []SliceInterface{s}
    i := []interface{}{s}
    sint := []int{1, 2, 3}

    ij := inject.New()
    ij.Map(s)
    fmt.Println(ij.Invoke(Handler1))
    fmt.Println(ij.Invoke(Handler2))
    fmt.Println(ij.Invoke(Handler3))

    ij.Map(si).Map(i).Map(sint)
    fmt.Println(ij.Invoke(Handler1))
    fmt.Println(ij.Invoke(Handler2))
    fmt.Println(ij.Invoke(Handler3))
}

I was thinking the code would look something like this:

func InterfaceOf(value interface{}) reflect.Type {
    t := reflect.TypeOf(value)

    for t.Kind() == reflect.Ptr {
        t = t.Elem()
    }

    if t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Interface {
        return t
    }

    if t.Kind() != reflect.Interface {
        panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil) but got " + t.Kind().String())
    }

    return t
}

func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
    t := reflect.TypeOf(f)

    var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
    for i := 0; i < t.NumIn(); i++ {
        argType := t.In(i)
        val := inj.Get(argType)
        if val.IsValid() {
            in[i] = val
            continue
        }
        if !val.IsValid() && t.IsVariadic() && i == t.NumIn()-1 {
            in[i] = reflect.New(argType).Elem()
            break
        }
        return nil, fmt.Errorf("Value not found for type %v", argType)
    }
    if t.IsVariadic() && len(in) == t.NumIn() {
        return reflect.ValueOf(f).CallSlice(in), nil
    }
    return reflect.ValueOf(f).Call(in), nil
}

Dependency Provider

It would be very nice if inject could control the dependency construction process, rather than the developer needing to manually instantiate them in the correct order and Map()'ing them in. This could be thought of as evaluating a dependency graph.

Something like this:

type Provider interface {
    Provide(ifacePtr interface{}, constructor func(*TypeMapper) interface{})
}

Then the TypeMapper, on request of a type that it does not have in is values map, would invoke the Provider to create it. Could also do some sort of infinite regression protection, too, in the event of an inadvertent dependency loop.

Alas, I can't think of a more declarative way to do it, and interface{} makes me sad.

What do you think, @codegangsta? I apologise for the presumptuous design ticket. ;)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.