support the variadic function
Opened this issue · 1 comments
achun commented
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 commented
I'm down with this idea.