feat(getControllers): allow objects for require

allowing objects, similar to $Q.all, read out more clearly for example
current ngModelDirective
```javascript
var ngModelDirective = function() {
  return {
    restrict: 'A',
    require: ['ngModel', '^?form', '^?ngModelOptions'],
    controller: NgModelController,
    link: {
      pre: function(scope, element, attr, ctrls) {
        // Pass the ng-model-options to the ng-model controller
        if (ctrls[2]) {
          ctrls[0].$options = ctrls[2].$options;
        }

        // notify others, especially parent forms

        var modelCtrl = ctrls[0],
            formCtrl = ctrls[1] || nullFormCtrl;

        formCtrl.$addControl(modelCtrl);

        scope.$on('$destroy', function() {
          formCtrl.$removeControl(modelCtrl);
        });
      },
      post: function(scope, element, attr, ctrls) {
        var modelCtrl = ctrls[0];
        if (modelCtrl.$options && modelCtrl.$options.updateOn) {
          element.on(modelCtrl.$options.updateOn, function(ev) {
            scope.$apply(function() {
              modelCtrl.$$debounceViewValueCommit(ev && ev.type);
            });
          });
        }

        element.on('blur', function(ev) {
          scope.$evalAsync(function() {
            modelCtrl.$setTouched();
          });
        });
      }
    }
  };
};
```


ngModelDirective with a require object
```javascript
var ngModelDirective = function() {
  return {
    restrict: 'A',
    require: {
      ngModel: 'ngModel',
      form: '^?form',
      ngModelOptions: '^?ngModelOptions'
    },
    controller: NgModelController,
    link: {
      pre: function(scope, element, attr, ctrls) {
        // Pass the ng-model-options to the ng-model controller
        if (ctrls.ngModelOptions) {
          ctrls.ngModel.$options = ctrls.ngModelOptions.$options;
        }

        // notify others, especially parent forms

        var modelCtrl = ctrls.ngModel,
            formCtrl = ctrls.form || nullFormCtrl;

        formCtrl.$addControl(modelCtrl);

        scope.$on('$destroy', function() {
          formCtrl.$removeControl(modelCtrl);
        });
      },
      post: function(scope, element, attr, ctrls) {
        var modelCtrl = ctrls.ngModel;
        if (modelCtrl.$options && modelCtrl.$options.updateOn) {
          element.on(modelCtrl.$options.updateOn, function(ev) {
            scope.$apply(function() {
              modelCtrl.$$debounceViewValueCommit(ev && ev.type);
            });
          });
        }

        element.on('blur', function(ev) {
          scope.$evalAsync(function() {
            modelCtrl.$setTouched();
          });
        });
      }
    }
  };
};
```
oops, yeah that's why you don't make PR's with github edits. I ran the unit tests locally with <code>key</code>  fix and had no errors