Example #1
0
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
	}
}
Example #2
0
// 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
}