func Inject(value reflect.Value, tagValue string) (bool, error) { if typeOfFile.AssignableTo(value.Type()) || typeOfFile.ConvertibleTo(value.Type()) { file, err := os.Open(tagValue) if err != nil { return false, err } fmt.Printf("%s\n", value) value.Elem().Set(reflect.ValueOf(file).Elem()) return true, nil } else { tag, optionalType := tags.ParseTag(tagValue) file, err := os.Open(tag) if err != nil { return false, err } fileType := string(optionalType) if fileType == "" { fileType = filepath.Ext(tag)[1:] } if fileType == "" { return false, fmt.Errorf("no extension or type option given for file: %s", tag) } switch fileType { case "txt": if bytes, err := ioutil.ReadAll(file); err != nil { return false, err } else { value.SetString(string(bytes)) } case "json": if err := json.NewDecoder(file).Decode(value.Interface()); err != nil { return false, err } case "xml": if err := xml.NewDecoder(file).Decode(value.Interface()); err != nil { return false, err } case "gob": if err := gob.NewDecoder(file).Decode(value.Interface()); err != nil { return false, err } default: return false, fmt.Errorf("unable to read file %s, unrecognized file type %s", tag, fileType) } return true, nil } }
// Binds modules. Calls Provide() on modules implementing Provider, calls inject.Injectors for tagged fields, and // injects provided fields. func (binder *Binder) Bind(modules ...interface{}) error { binding := newBinding(binder) // Holds errors during binding. errs := make([]error, 0) // Validate configuration if _, ok := binding.injectors["provide"]; ok { return errors.New("the 'provide' tag key may not be overridden") } if _, ok := binding.injectors["inject"]; ok { return errors.New("the 'inject' tag key may not be overridden") } // Collect errors in a goroutine. go func() { for err := range binding.errors { errs = append(errs, err) } }() // Injection goroutines signal here when complete. var injections sync.WaitGroup // Bind each module. for _, module := range modules { // If this module is a Provider then call Provide(). if provider, ok := module.(Provider); ok { if err := provider.Provide(); err != nil { return &AnnotatedError{msg: "error during call to Provide()", cause: err} } } // Bind each field in this module. moduleType := reflect.TypeOf(module).Elem() for i := 0; i < moduleType.NumField(); i++ { field := moduleType.Field(i) value := reflect.ValueOf(module).Elem().Field(i) tag := tags.StructTag(string(field.Tag)) if bindName, ok := tag.Get("inject"); ok { if !value.CanSet() { binding.errors <- fmt.Errorf("cannot inject unexported field: %s", field.Name) continue } injections.Add(1) go func() { // Blocks until a provider binds key, or cancelled. binding.inject(bindName, value) injections.Done() }() } else if tagValue, ok := tag.Get("provide"); ok { bindName, options := tags.ParseTag(tagValue) // Releases blocking injections for key. if err := binding.provide(bindName, options.Contains("singleton"), tag, value); err != nil { binding.errors <- err } } } } // Wait for all injection goroutines to complete. injections.Wait() // Signal error processing goroutine to complete. close(binding.errors) if len(errs) > 0 { return &BindingError{errs} } return nil }