Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support the variadic function #11

Open
achun opened this issue Jan 15, 2014 · 1 comment
Open

support the variadic function #11

achun opened this issue Jan 15, 2014 · 1 comment

Comments

@achun
Copy link

achun commented Jan 15, 2014

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
}
@codegangsta
Copy link
Owner

I'm down with this idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants