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:
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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';
|
||||
|
@ -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[];
|
||||
|
@ -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);
|
||||
}
|
@ -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();
|
||||
* ```
|
||||
*/
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user