refactor(Provider): remove deprecated provider/bind API (#10652)

Closes #9751

BREAKING CHANGE:

These forms of providers are no longer accepted:
  bind(MyClass).toFactory(...)
  new Provider(MyClass, toFactory: ...)

We now only accept:
  {provider: MyClass, toFactory: ...}
This commit is contained in:
Miško Hevery
2016-08-15 19:37:42 -07:00
committed by vikerman
parent 04c11bb749
commit bec5c5fdad
47 changed files with 497 additions and 639 deletions

View File

@ -80,7 +80,8 @@ export class IterableDiffers {
* ```
*/
static extend(factories: IterableDifferFactory[]): Provider {
return new Provider(IterableDiffers, {
return {
provide: IterableDiffers,
useFactory: (parent: IterableDiffers) => {
if (isBlank(parent)) {
// Typically would occur when calling IterableDiffers.extend inside of dependencies passed
@ -92,7 +93,7 @@ export class IterableDiffers {
},
// Dependency technically isn't optional, but we can provide a better error message this way.
deps: [[IterableDiffers, new SkipSelfMetadata(), new OptionalMetadata()]]
});
};
}
find(iterable: any): IterableDifferFactory {

View File

@ -70,7 +70,8 @@ export class KeyValueDiffers {
* ```
*/
static extend(factories: KeyValueDifferFactory[]): Provider {
return new Provider(KeyValueDiffers, {
return {
provide: KeyValueDiffers,
useFactory: (parent: KeyValueDiffers) => {
if (isBlank(parent)) {
// Typically would occur when calling KeyValueDiffers.extend inside of dependencies passed
@ -82,7 +83,7 @@ export class KeyValueDiffers {
},
// Dependency technically isn't optional, but we can provide a better error message this way.
deps: [[KeyValueDiffers, new SkipSelfMetadata(), new OptionalMetadata()]]
});
};
}
find(kv: Object): KeyValueDifferFactory {

View File

@ -22,7 +22,7 @@ export {forwardRef, resolveForwardRef, ForwardRefFn} from './di/forward_ref';
export {Injector} from './di/injector';
export {ReflectiveInjector} from './di/reflective_injector';
export {Binding, ProviderBuilder, bind, Provider, provide} from './di/provider';
export {Provider, TypeProvider, ValueProvider, ClassProvider, ExistingProvider, FactoryProvider} from './di/provider';
export {ResolvedReflectiveBinding, ResolvedReflectiveFactory, ResolvedReflectiveProvider} from './di/reflective_provider';
export {ReflectiveKey} from './di/reflective_key';
export {NoProviderError, AbstractProviderError, CyclicDependencyError, InstantiationError, InvalidProviderError, NoAnnotationError, OutOfBoundsError} from './di/reflective_exceptions';

View File

@ -6,410 +6,344 @@
* found in the LICENSE file at https://angular.io/license
*/
import {BaseException} from '../facade/exceptions';
import {isBlank, isFunction, isType, normalizeBool, stringify} from '../facade/lang';
import {Type} from '../type';
/**
* Describes how the {@link Injector} should instantiate a given token.
* Configures the {@link Injector} to return an instance of `Type` when `Type' is used as token.
*
* See {@link provide}.
*
* ### Example ([live demo](http://plnkr.co/edit/GNAyj6K6PfYg2NBzgwZ5?p%3Dpreview&p=preview))
* Create an instance by invoking the `new` operator and supplying additional arguments.
* This form is a short form of `TypeProvider`;
*
* ### Example
* ```javascript
* var injector = Injector.resolveAndCreate([
* new Provider("message", { useValue: 'Hello' })
* @Injectable()
* class Greeting {
* text: 'Hello';
* }
*
* @Injectable()
* class MyClass {
* greeting:string;
* constructor(greeting: Greeting) {
* this.greeting = greeting.text;
* }
* }
*
* const injector = Injector.resolveAndCreate([
* Greeting, // Shorthand for { provide: Greeting, useClass: Greeting }
* MyClass // Shorthand for { provide: MyClass, useClass: MyClass }
* ]);
*
* expect(injector.get("message")).toEqual('Hello');
* const myClass: MyClass = injector.get(MyClass);
* expect(myClass.greeting).toEqual('Hello');
* ```
* @deprecated
*
* @stable
*/
export class Provider {
export interface TypeProvider extends Type<any> {}
/**
* Configures the {@link Injector} to return a value for a token.
*
* ### Example
* const injector = Injector.resolveAndCreate([
* {provide: String, useValue: 'Hello'}
* ]);
*
* expect(injector.get(String)).toEqual('Hello');
* ```
* @stable
*/
export interface ValueProvider {
/**
* Token used when retrieving this provider. Usually, it is a type {@link Type}.
* An injection token. (Typically an instance of `Type` or `OpaqueToken`, but can be `any`).
*/
token: any;
provide: any;
/**
* Binds a DI token to an implementation class.
*
* ### Example ([live demo](http://plnkr.co/edit/RSTG86qgmoxCyj9SWPwY?p=preview))
*
* Because `useExisting` and `useClass` are often confused, the example contains
* both use cases for easy comparison.
*
* ```typescript
* class Vehicle {}
*
* class Car extends Vehicle {}
*
* var injectorClass = Injector.resolveAndCreate([
* Car,
* {provide: Vehicle, useClass: Car }
* ]);
* var injectorAlias = Injector.resolveAndCreate([
* Car,
* {provide: Vehicle, useExisting: Car }
* ]);
*
* expect(injectorClass.get(Vehicle)).not.toBe(injectorClass.get(Car));
* expect(injectorClass.get(Vehicle) instanceof Car).toBe(true);
*
* expect(injectorAlias.get(Vehicle)).toBe(injectorAlias.get(Car));
* expect(injectorAlias.get(Vehicle) instanceof Car).toBe(true);
* ```
*/
useClass: Type<any>;
/**
* Binds a DI token to a value.
*
* ### Example ([live demo](http://plnkr.co/edit/UFVsMVQIDe7l4waWziES?p=preview))
*
* ```javascript
* var injector = Injector.resolveAndCreate([
* new Provider("message", { useValue: 'Hello' })
* ]);
*
* expect(injector.get("message")).toEqual('Hello');
* ```
* The value to inject.
*/
useValue: any;
/**
* Binds a DI token to an existing token.
* If true, than injector returns an array of instances. This is useful to allow multiple
* providers spread across many files to provide configuration information to a common token.
*
* {@link Injector} returns the same instance as if the provided token was used.
* This is in contrast to `useClass` where a separate instance of `useClass` is returned.
* ### Example
* ```javascript
* var locale = new OpaqueToken('local');
*
* ### Example ([live demo](http://plnkr.co/edit/QsatsOJJ6P8T2fMe9gr8?p=preview))
*
* Because `useExisting` and `useClass` are often confused the example contains
* both use cases for easy comparison.
*
* ```typescript
* class Vehicle {}
*
* class Car extends Vehicle {}
*
* var injectorAlias = Injector.resolveAndCreate([
* Car,
* {provide: Vehicle, useExisting: Car }
* ]);
* var injectorClass = Injector.resolveAndCreate([
* Car,
* {provide: Vehicle, useClass: Car }
* const injector = Injector.resolveAndCreate([
* { provide: locale, useValue: 'en' },
* { provide: locale, useValue: 'sk' },
* ]);
*
* expect(injectorAlias.get(Vehicle)).toBe(injectorAlias.get(Car));
* expect(injectorAlias.get(Vehicle) instanceof Car).toBe(true);
*
* expect(injectorClass.get(Vehicle)).not.toBe(injectorClass.get(Car));
* expect(injectorClass.get(Vehicle) instanceof Car).toBe(true);
* const locales: string[] = injector.get(locale);
* expect(locales).toEqual(['en', 'sk']);
* ```
*/
multi?: boolean;
}
/**
* Configures the {@link Injector} to return an instance of `useClass` for a token.
*
* ### Example
* ```javascript
* abstract class Shape {
* name: string;
* }
*
* class Square extends Shape {
* name = 'square';
* }
*
* const injector = Injector.resolveAndCreate([
* {provide: Shape, useClass: Square}
* ]);
*
* const shape: Shape = injector.get(Shape);
* expect(shape.name).toEqual('square');
* expect(shape instanceof Square).toBe(true);
* ```
*
* Note that following is not equal:
* ```javascript
* class Greeting {
* salutation = 'Hello';
* }
*
* class FormalGreeting extends Greeting {
* salutation = 'Greetings';
* }
*
* const injector = Injector.resolveAndCreate([
* FormalGreeting,
* {provide: Greeting, useClass: FormalGreeting}
* ]);
*
* // The injector returns different instances.
* // See: {provide: ?, useExisting: ?} if you want the same instance.
* expect(injector.get(FormalGreeting)).not.toBe(injector.get(Greeting));
* ```
*
* @stable
*/
export interface ClassProvider {
/**
* An injection token. (Typically an instance of `Type` or `OpaqueToken`, but can be `any`).
*/
provide: any;
/**
* Class to instantiate for the `token`.
*/
useClass: Type<any>;
/**
* If true, than injector returns an array of instances. This is useful to allow multiple
* providers spread across many files to provide configuration information to a common token.
*
* ### Example
* ```javascript
* abstract class Locale {
* name: string;
* };
*
* @Injectable()
* class EnLocale extends Locale {
* name: 'en';
* };
*
* @Injectable()
* class SkLocale extends Locale {
* name: 'sk';
* };
*
* const injector = Injector.resolveAndCreate([
* { provide: Locale, useValue: EnLocale, multi: true },
* { provide: Locale, useValue: SkLocale, multi: true },
* ]);
*
* const locales: Locale[] = injector.get(Locale);
* const localeNames: string[] = locals.map((l) => l.name);
* expect(localeNames).toEqual(['en', 'sk']);
* ```
*/
multi?: boolean;
}
/**
* Configures the {@link Injector} to return a value of another `useExisting` token.
*
* ### Example
* ```javascript
* class Greeting {
* salutation = 'Hello';
* }
*
* class FormalGreeting extends Greeting {
* salutation = 'Greetings';
* }
*
* const injector = Injector.resolveAndCreate([
* FormalGreeting,
* {provide: Greeting, useExisting: FormalGreeting}
* ]);
*
* expect(injector.get(Greeting).name).toEqual('Hello');
* expect(injector.get(FormalGreeting).name).toEqual('Hello');
* expect(injector.get(Salutation).name).toBe(injector.get(Greeting));
* ```
* @stable
*/
export interface ExistingProvider {
/**
* An injection token. (Typically an instance of `Type` or `OpaqueToken`, but can be `any`).
*/
provide: any;
/**
* Existing `token` to return. (equivalent to `injector.get(useExisting)`)
*/
useExisting: any;
/**
* Binds a DI token to a function which computes the value.
* If true, than injector returns an array of instances. This is useful to allow multiple
* providers spread across many files to provide configuration information to a common token.
*
* ### Example ([live demo](http://plnkr.co/edit/Scoxy0pJNqKGAPZY1VVC?p=preview))
* ### Example
* ```javascript
* abstract class Locale {
* name: string;
* };
*
* ```typescript
* var injector = Injector.resolveAndCreate([
* {provide: Number, useFactory: () => { return 1+2; }},
* new Provider(String, { useFactory: (value) => { return "Value: " + value; },
* deps: [Number] })
* @Injectable()
* class EnLocale extends Locale {
* name: 'en';
* };
*
* @Injectable()
* class SkLocale extends Locale {
* name: 'sk';
* };
*
* const injector = Injector.resolveAndCreate([
* EnLocale,
* SkLocale
* { provide: Locale, useExisting: EnLocale, multi: true },
* { provide: Locale, useExisting: SkLocale, multi: true },
* ]);
*
* expect(injector.get(Number)).toEqual(3);
* expect(injector.get(String)).toEqual('Value: 3');
* const locales: Locale[] = injector.get(Locale);
* const localeNames: string[] = locals.map((l) => l.name);
* expect(localeNames).toEqual(['en', 'sk']);
* ```
*
* Used in conjunction with dependencies.
*/
multi?: boolean;
}
/**
* Configures the {@link Injector} to return a value by invoking a `useFactory` function.
*
* ### Example
* ```javascript
* const HASH = new OpaqueToken('hash');
*
* const injector = Injector.resolveAndCreate([
* {provide: Location, useValue: window.location},
* {provide: HASH, useFactory: (location: Location) => location.hash, deps: [Location]}
* ]);
*
*
* // Assume location is: http://angular.io/#someLocation
* expect(injector.get(HASH)).toEqual('someLocation');
* ``
* @stable
*/
export interface FactoryProvider {
/**
* An injection token. (Typically an instance of `Type` or `OpaqueToken`, but can be `any`).
*/
provide: any;
/**
* A function to invoke to create a value for this `token`. The function is invoked with
* resolved values of `token`s in the `deps` field.
*/
useFactory: Function;
/**
* Specifies a set of dependencies
* (as `token`s) which should be injected into the factory function.
*
* ### Example ([live demo](http://plnkr.co/edit/Scoxy0pJNqKGAPZY1VVC?p=preview))
*
* ```typescript
* var injector = Injector.resolveAndCreate([
* {provide: Number, useFactory: () => { return 1+2; }},
* new Provider(String, { useFactory: (value) => { return "Value: " + value; },
* deps: [Number] })
* ]);
*
* expect(injector.get(Number)).toEqual(3);
* expect(injector.get(String)).toEqual('Value: 3');
* ```
*
* Used in conjunction with `useFactory`.
* A list of `token`s which need to be resolved by the injector. The list of values is than
* used as arguments to the `useFactory` function.
*/
dependencies: Object[];
deps: any[];
/** @internal */
_multi: boolean;
constructor(token: any, {useClass, useValue, useExisting, useFactory, deps, multi}: {
useClass?: Type<any>,
useValue?: any,
useExisting?: any,
useFactory?: Function,
deps?: Object[],
multi?: boolean
}) {
this.token = token;
this.useClass = useClass;
this.useValue = useValue;
this.useExisting = useExisting;
this.useFactory = useFactory;
this.dependencies = deps;
this._multi = multi;
}
// TODO: Provide a full working example after alpha38 is released.
/**
* Creates multiple providers matching the same token (a multi-provider).
*
* Multi-providers are used for creating pluggable service, where the system comes
* with some default providers, and the user can register additional providers.
* The combination of the default providers and the additional providers will be
* used to drive the behavior of the system.
* If true, than injector returns an array of instances. This is useful to allow multiple
* providers spread across many files to provide configuration information to a common token.
*
* ### Example
* ```javascript
* class Locale {
* constructor(public name: string) {}
* };
* const PRIMARY = new OpequeToken('primary');
* const SECONDARY = new OpequeToken('secondary');
*
* ```typescript
* var injector = Injector.resolveAndCreate([
* new Provider("Strings", { useValue: "String1", multi: true}),
* new Provider("Strings", { useValue: "String2", multi: true})
* const injector = Injector.resolveAndCreate([
* { provide: PRIMARY: useValue: 'en'},
* { provide: SECONDARY: useValue: 'sk'},
* { provide: Locale, useFactory: (n) => new Locale(n), deps: [PRIMARY], multi: true},
* { provide: Locale, useFactory: (n) => new Locale(n), deps: [SECONDARY], multi: true},
* ]);
*
* expect(injector.get("Strings")).toEqual(["String1", "String2"]);
* ```
*
* Multi-providers and regular providers cannot be mixed. The following
* will throw an exception:
*
* ```typescript
* var injector = Injector.resolveAndCreate([
* new Provider("Strings", { useValue: "String1", multi: true }),
* new Provider("Strings", { useValue: "String2"})
* ]);
* const locales: Locale[] = injector.get(Locale);
* const localeNames: string[] = locals.map((l) => l.name);
* expect(localeNames).toEqual(['en', 'sk']);
* ```
*/
get multi(): boolean { return normalizeBool(this._multi); }
multi?: boolean;
}
/**
* See {@link Provider} instead.
* Describes how the {@link Injector} should be configured.
*
* @deprecated
* See {@link TypeProvider}, {@link ValueProvider}, {@link ClassProvider}, {@link ExistingProvider},
* {@link FactoryProvider}.
*
* ```javascript
* class Greeting {
* salutation = 'Hello';
* }
*
* class FormalGreeting extends Greeting {
* salutation = 'Greetings';
* }
*
* abstract class Operation {
* apply(a,b): any;
* }
*
* class AddOperation extends Operation {
* apply(a,b) { return a+b; }
* }
*
*
* const injector = Injector.resolveAndCreate([
* FormalGreeting,
* {provide: String, useValue: 'Hello World!'},
* {provide: Greeting, useExisting: FormalGreeting},
* {provide: Operation, useClass: AddOperation},
* {provide: Number, useFactory: (op) =>op.apply(1,2), deps: [Operation] }
* ]);
*
* expect(injector.get(FormalGreeting).name).toEqual('Greetings');
* expect(injector.get(String).name).toEqual('Hello World!');
* expect(injector.get(Greeting).name).toBe(injector.get(FormalGreeting));
* expect(injector.get(Number).toEqual(3);
* ```
* @stable
*/
export class Binding extends Provider {
constructor(token: any, {toClass, toValue, toAlias, toFactory, deps, multi}: {
toClass?: Type<any>,
toValue?: any,
toAlias?: any,
toFactory: Function, deps?: Object[], multi?: boolean
}) {
super(token, {
useClass: toClass,
useValue: toValue,
useExisting: toAlias,
useFactory: toFactory,
deps: deps,
multi: multi
});
}
/**
* @deprecated
*/
get toClass() { return this.useClass; }
/**
* @deprecated
*/
get toAlias() { return this.useExisting; }
/**
* @deprecated
*/
get toFactory() { return this.useFactory; }
/**
* @deprecated
*/
get toValue() { return this.useValue; }
}
/**
* Creates a {@link Provider}.
*
* To construct a {@link Provider}, bind a `token` to either a class, a value, a factory function,
* or
* to an existing `token`.
* See {@link ProviderBuilder} for more details.
*
* The `token` is most commonly a class or {@link OpaqueToken}.
*
* @deprecated
*/
export function bind(token: any): ProviderBuilder {
return new ProviderBuilder(token);
}
/**
* Helper class for the {@link bind} function.
* @deprecated
*/
export class ProviderBuilder {
constructor(public token: any) {}
/**
* Binds a DI token to a class.
*
* ### Example ([live demo](http://plnkr.co/edit/ZpBCSYqv6e2ud5KXLdxQ?p=preview))
*
* Because `toAlias` and `toClass` are often confused, the example contains
* both use cases for easy comparison.
*
* ```typescript
* class Vehicle {}
*
* class Car extends Vehicle {}
*
* var injectorClass = Injector.resolveAndCreate([
* Car,
* {provide: Vehicle, useClass: Car}
* ]);
* var injectorAlias = Injector.resolveAndCreate([
* Car,
* {provide: Vehicle, useExisting: Car}
* ]);
*
* expect(injectorClass.get(Vehicle)).not.toBe(injectorClass.get(Car));
* expect(injectorClass.get(Vehicle) instanceof Car).toBe(true);
*
* expect(injectorAlias.get(Vehicle)).toBe(injectorAlias.get(Car));
* expect(injectorAlias.get(Vehicle) instanceof Car).toBe(true);
* ```
*/
toClass(type: Type<any>): Provider {
if (!isType(type)) {
throw new BaseException(
`Trying to create a class provider but "${stringify(type)}" is not a class!`);
}
return new Provider(this.token, {useClass: type});
}
/**
* Binds a DI token to a value.
*
* ### Example ([live demo](http://plnkr.co/edit/G024PFHmDL0cJFgfZK8O?p=preview))
*
* ```typescript
* var injector = Injector.resolveAndCreate([
* {provide: 'message', useValue: 'Hello'}
* ]);
*
* expect(injector.get('message')).toEqual('Hello');
* ```
*/
toValue(value: any): Provider { return new Provider(this.token, {useValue: value}); }
/**
* Binds a DI token to an existing token.
*
* Angular will return the same instance as if the provided token was used. (This is
* in contrast to `useClass` where a separate instance of `useClass` will be returned.)
*
* ### Example ([live demo](http://plnkr.co/edit/uBaoF2pN5cfc5AfZapNw?p=preview))
*
* Because `toAlias` and `toClass` are often confused, the example contains
* both use cases for easy comparison.
*
* ```typescript
* class Vehicle {}
*
* class Car extends Vehicle {}
*
* var injectorAlias = Injector.resolveAndCreate([
* Car,
* {provide: Vehicle, useExisting: Car}
* ]);
* var injectorClass = Injector.resolveAndCreate([
* Car,
* {provide: Vehicle, useClass: Car})
* ]);
*
* expect(injectorAlias.get(Vehicle)).toBe(injectorAlias.get(Car));
* expect(injectorAlias.get(Vehicle) instanceof Car).toBe(true);
*
* expect(injectorClass.get(Vehicle)).not.toBe(injectorClass.get(Car));
* expect(injectorClass.get(Vehicle) instanceof Car).toBe(true);
* ```
*/
toAlias(aliasToken: /*Type*/ any): Provider {
if (isBlank(aliasToken)) {
throw new BaseException(`Can not alias ${stringify(this.token)} to a blank value!`);
}
return new Provider(this.token, {useExisting: aliasToken});
}
/**
* Binds a DI token to a function which computes the value.
*
* ### Example ([live demo](http://plnkr.co/edit/OejNIfTT3zb1iBxaIYOb?p=preview))
*
* ```typescript
* var injector = Injector.resolveAndCreate([
* {provide: Number, useFactory: () => { return 1+2; }},
* {provide: String, useFactory: (v) => { return "Value: " + v; }, deps: [Number]}
* ]);
*
* expect(injector.get(Number)).toEqual(3);
* expect(injector.get(String)).toEqual('Value: 3');
* ```
*/
toFactory(factory: Function, dependencies?: any[]): Provider {
if (!isFunction(factory)) {
throw new BaseException(
`Trying to create a factory provider but "${stringify(factory)}" is not a function!`);
}
return new Provider(this.token, {useFactory: factory, deps: dependencies});
}
}
/**
* Creates a {@link Provider}.
*
* See {@link Provider} for more details.
*
* <!-- TODO: improve the docs -->
* @deprecated
*/
export function provide(token: any, {useClass, useValue, useExisting, useFactory, deps, multi}: {
useClass?: Type<any>,
useValue?: any,
useExisting?: any,
useFactory?: Function,
deps?: Object[],
multi?: boolean
}): Provider {
return new Provider(token, {
useClass: useClass,
useValue: useValue,
useExisting: useExisting,
useFactory: useFactory,
deps: deps,
multi: multi
});
}
export type Provider =
TypeProvider | ValueProvider | ClassProvider | ExistingProvider | FactoryProvider | any[];

View File

@ -1,17 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Provider} from './provider';
export function isProviderLiteral(obj: any): boolean {
return obj && typeof obj == 'object' && obj.provide;
}
export function createProvider(obj: any): Provider {
return new Provider(obj.provide, obj);
}

View File

@ -10,8 +10,6 @@ import {ListWrapper} from '../facade/collection';
import {BaseException, WrappedException} from '../facade/exceptions';
import {isBlank, stringify} from '../facade/lang';
import {Type} from '../type';
import {Provider} from './provider';
import {ReflectiveInjector} from './reflective_injector';
import {ReflectiveKey} from './reflective_key';
@ -273,8 +271,8 @@ export class OutOfBoundsError extends BaseException {
*
* ```typescript
* expect(() => Injector.resolveAndCreate([
* new Provider("Strings", {useValue: "string1", multi: true}),
* new Provider("Strings", {useValue: "string2", multi: false})
* { provide: "Strings", useValue: "string1", multi: true},
* { provide: "Strings", useValue: "string2", multi: false}
* ])).toThrowError();
* ```
*/

View File

@ -392,8 +392,7 @@ export abstract class ReflectiveInjector implements Injector {
*
* See {@link ReflectiveInjector#fromResolvedProviders} for more info.
*/
static resolve(providers: Array<Type<any>|Provider|{[k: string]: any}|any[]>):
ResolvedReflectiveProvider[] {
static resolve(providers: Provider[]): ResolvedReflectiveProvider[] {
return resolveReflectiveProviders(providers);
}
@ -423,9 +422,7 @@ export abstract class ReflectiveInjector implements Injector {
* because it needs to resolve the passed-in providers first.
* See {@link Injector#resolve} and {@link Injector#fromResolvedProviders}.
*/
static resolveAndCreate(
providers: Array<Type<any>|Provider|{[k: string]: any}|any[]>,
parent: Injector = null): ReflectiveInjector {
static resolveAndCreate(providers: Provider[], parent: Injector = null): ReflectiveInjector {
var ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent);
}
@ -516,10 +513,7 @@ export abstract class ReflectiveInjector implements Injector {
* because it needs to resolve the passed-in providers first.
* See {@link Injector#resolve} and {@link Injector#createChildFromResolved}.
*/
resolveAndCreateChild(providers: Array<Type<any>|Provider|{[k: string]: any}|any[]>):
ReflectiveInjector {
return unimplemented();
}
resolveAndCreateChild(providers: Provider[]): ReflectiveInjector { return unimplemented(); }
/**
* Creates a child injector from previously resolved providers.
@ -574,7 +568,7 @@ export abstract class ReflectiveInjector implements Injector {
* expect(car).not.toBe(injector.resolveAndInstantiate(Car));
* ```
*/
resolveAndInstantiate(provider: Type<any>|Provider): any { return unimplemented(); }
resolveAndInstantiate(provider: Provider): any { return unimplemented(); }
/**
* Instantiates an object using a resolved provider in the context of the injector.
@ -644,7 +638,7 @@ export class ReflectiveInjector_ implements ReflectiveInjector {
*/
get internalStrategy(): any { return this._strategy; }
resolveAndCreateChild(providers: Array<Type<any>|Provider|any[]>): ReflectiveInjector {
resolveAndCreateChild(providers: Provider[]): ReflectiveInjector {
var ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
return this.createChildFromResolved(ResolvedReflectiveProviders);
}
@ -656,7 +650,7 @@ export class ReflectiveInjector_ implements ReflectiveInjector {
return inj;
}
resolveAndInstantiate(provider: Type<any>|Provider): any {
resolveAndInstantiate(provider: Provider): any {
return this.instantiateResolved(ReflectiveInjector.resolve([provider])[0]);
}

View File

@ -13,12 +13,13 @@ import {Type} from '../type';
import {resolveForwardRef} from './forward_ref';
import {DependencyMetadata, HostMetadata, InjectMetadata, OptionalMetadata, SelfMetadata, SkipSelfMetadata} from './metadata';
import {Provider, ProviderBuilder, provide} from './provider';
import {createProvider, isProviderLiteral} from './provider_util';
import {ClassProvider, ExistingProvider, FactoryProvider, Provider, TypeProvider, ValueProvider} from './provider';
import {InvalidProviderError, MixingMultiProvidersWithRegularProvidersError, NoAnnotationError} from './reflective_exceptions';
import {ReflectiveKey} from './reflective_key';
interface NormalizedProvider extends TypeProvider, ValueProvider, ClassProvider, ExistingProvider,
FactoryProvider {}
/**
* `Dependency` is used by the framework to extend DI.
@ -46,7 +47,7 @@ const _EMPTY_LIST: any[] = [];
* ### Example ([live demo](http://plnkr.co/edit/RfEnhh8kUEI0G3qsnIeT?p%3Dpreview&p=preview))
*
* ```typescript
* var resolvedProviders = Injector.resolve([new Provider('message', {useValue: 'Hello'})]);
* var resolvedProviders = Injector.resolve([{ provide: 'message', useValue: 'Hello' }]);
* var injector = Injector.fromResolvedProviders(resolvedProviders);
*
* expect(injector.get('message')).toEqual('Hello');
@ -87,7 +88,8 @@ export class ResolvedReflectiveProvider_ implements ResolvedReflectiveBinding {
}
/**
* An internal resolved representation of a factory function created by resolving {@link Provider}.
* An internal resolved representation of a factory function created by resolving {@link
* Provider}.
* @experimental
*/
export class ResolvedReflectiveFactory {
@ -107,7 +109,7 @@ export class ResolvedReflectiveFactory {
/**
* Resolve a single provider.
*/
export function resolveReflectiveFactory(provider: Provider): ResolvedReflectiveFactory {
function resolveReflectiveFactory(provider: NormalizedProvider): ResolvedReflectiveFactory {
var factoryFn: Function;
var resolvedDeps: ReflectiveDependency[];
if (isPresent(provider.useClass)) {
@ -119,7 +121,7 @@ export function resolveReflectiveFactory(provider: Provider): ResolvedReflective
resolvedDeps = [ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting))];
} else if (isPresent(provider.useFactory)) {
factoryFn = provider.useFactory;
resolvedDeps = constructDependencies(provider.useFactory, provider.dependencies);
resolvedDeps = constructDependencies(provider.useFactory, provider.deps);
} else {
factoryFn = () => provider.useValue;
resolvedDeps = _EMPTY_LIST;
@ -133,16 +135,15 @@ export function resolveReflectiveFactory(provider: Provider): ResolvedReflective
* {@link Injector} internally only uses {@link ResolvedProvider}, {@link Provider} contains
* convenience provider syntax.
*/
export function resolveReflectiveProvider(provider: Provider): ResolvedReflectiveProvider {
function resolveReflectiveProvider(provider: NormalizedProvider): ResolvedReflectiveProvider {
return new ResolvedReflectiveProvider_(
ReflectiveKey.get(provider.token), [resolveReflectiveFactory(provider)], provider.multi);
ReflectiveKey.get(provider.provide), [resolveReflectiveFactory(provider)], provider.multi);
}
/**
* Resolve a list of Providers.
*/
export function resolveReflectiveProviders(
providers: Array<Type<any>|Provider|{[k: string]: any}|any[]>): ResolvedReflectiveProvider[] {
export function resolveReflectiveProviders(providers: Provider[]): ResolvedReflectiveProvider[] {
var normalized = _normalizeProviders(providers, []);
var resolved = normalized.map(resolveReflectiveProvider);
return MapWrapper.values(
@ -186,25 +187,17 @@ export function mergeResolvedReflectiveProviders(
return normalizedProvidersMap;
}
function _normalizeProviders(
providers: Array<Type<any>|Provider|{[k: string]: any}|ProviderBuilder|any[]>,
res: Provider[]): Provider[] {
function _normalizeProviders(providers: Provider[], res: Provider[]): Provider[] {
providers.forEach(b => {
if (b instanceof Type) {
res.push(provide(b, {useClass: b}));
res.push({provide: b, useClass: b});
} else if (b instanceof Provider) {
res.push(b);
} else if (isProviderLiteral(b)) {
res.push(createProvider(b));
} else if (b && typeof b == 'object' && b.hasOwnProperty('provide')) {
res.push(b as NormalizedProvider);
} else if (b instanceof Array) {
_normalizeProviders(b, res);
} else if (b instanceof ProviderBuilder) {
throw new InvalidProviderError(b.token);
} else {
throw new InvalidProviderError(b);
}

View File

@ -9,7 +9,7 @@
import {NgModuleFactory} from './ng_module_factory';
/**
* Used to load ng moduled factories.
* Used to load ng module factories.
* @experimental
*/
export abstract class NgModuleFactoryLoader {

View File

@ -12,13 +12,12 @@ import {Provider} from './di';
import {Reflector, reflector} from './reflection/reflection';
import {ReflectorReader} from './reflection/reflector_reader';
import {TestabilityRegistry} from './testability/testability';
import {Type} from './type';
function _reflector(): Reflector {
return reflector;
}
const _CORE_PLATFORM_PROVIDERS: Array<any|Type<any>|Provider|any[]> = [
const _CORE_PLATFORM_PROVIDERS: Provider[] = [
PlatformRef_, {provide: PlatformRef, useExisting: PlatformRef_},
{provide: Reflector, useFactory: _reflector, deps: []},
{provide: ReflectorReader, useExisting: Reflector}, TestabilityRegistry, Console