parent
794e3870c5
commit
b0effe8e27
|
@ -11,8 +11,6 @@ import {EventEmitter, ObservableWrapper} from 'angular2/src/core/facade/async';
|
|||
import {ListWrapper, MapWrapper, StringMapWrapper} from 'angular2/src/core/facade/collection';
|
||||
import {
|
||||
Injector,
|
||||
ProtoInjector,
|
||||
Visibility,
|
||||
Key,
|
||||
Dependency,
|
||||
bind,
|
||||
|
@ -24,8 +22,10 @@ import {
|
|||
resolveForwardRef,
|
||||
DependencyProvider
|
||||
} from 'angular2/src/core/di';
|
||||
import {UNDEFINED} from 'angular2/src/core/di/injector';
|
||||
import {
|
||||
UNDEFINED,
|
||||
ProtoInjector,
|
||||
Visibility,
|
||||
InjectorInlineStrategy,
|
||||
InjectorDynamicStrategy,
|
||||
BindingWithVisibility
|
||||
|
|
|
@ -18,13 +18,7 @@ export {
|
|||
export * from './di/decorators';
|
||||
|
||||
export {forwardRef, resolveForwardRef, ForwardRefFn} from './di/forward_ref';
|
||||
export {
|
||||
Injector,
|
||||
ProtoInjector,
|
||||
BindingWithVisibility,
|
||||
DependencyProvider,
|
||||
Visibility
|
||||
} from './di/injector';
|
||||
export {Injector, DependencyProvider} from './di/injector';
|
||||
export {
|
||||
Binding,
|
||||
BindingBuilder,
|
||||
|
|
|
@ -207,6 +207,11 @@ export class Binding {
|
|||
/**
|
||||
* Creates multiple bindings matching the same token (a multi-binding).
|
||||
*
|
||||
* Multi-bindings are used for creating pluggable service, where the system comes
|
||||
* with some default bindings, and the user can register additonal bindings.
|
||||
* The combination of the default bindings and the additional bindings will be
|
||||
* used to drive the behavior of the system.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* ```typescript
|
||||
|
|
|
@ -195,6 +195,18 @@ export class InvalidBindingError extends BaseException {
|
|||
*
|
||||
* expect(() => Injector.resolveAndCreate([A])).toThrowError();
|
||||
* ```
|
||||
*
|
||||
* This error is also thrown when the class not marked with {@link @Injectable} has parameter types.
|
||||
*
|
||||
* ```typescript
|
||||
* class B {}
|
||||
*
|
||||
* class A {
|
||||
* constructor(b:B) {} // no information about the parameter types of A is available at runtime.
|
||||
* }
|
||||
*
|
||||
* expect(() => Injector.resolveAndCreate([A,B])).toThrowError();
|
||||
* ```
|
||||
*/
|
||||
export class NoAnnotationError extends BaseException {
|
||||
constructor(typeOrFunc, params: any[][]) {
|
||||
|
|
|
@ -394,76 +394,103 @@ export interface DependencyProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* A dependency injection container used for resolving dependencies.
|
||||
* A dependency injection container used for instantiating objects and resolving dependencies.
|
||||
*
|
||||
* An `Injector` is a replacement for a `new` operator, which can automatically resolve the
|
||||
* constructor dependencies.
|
||||
*
|
||||
* In typical use, application code asks for the dependencies in the constructor and they are
|
||||
* resolved by the `Injector`.
|
||||
*
|
||||
* ## Example:
|
||||
* ### Example ([live demo](http://plnkr.co/edit/jzjec0?p=preview))
|
||||
*
|
||||
* Suppose that we want to inject an `Engine` into class `Car`, we would define it like this:
|
||||
* The following example creates an `Injector` configured to create `Engine` and `Car`.
|
||||
*
|
||||
* ```javascript
|
||||
* ```typescript
|
||||
* @Injectable()
|
||||
* class Engine {
|
||||
* }
|
||||
*
|
||||
* @Injectable()
|
||||
* class Car {
|
||||
* constructor(@Inject(Engine) engine) {
|
||||
* }
|
||||
* constructor(public engine:Engine) {}
|
||||
* }
|
||||
*
|
||||
* var injector = Injector.resolveAndCreate([Car, Engine]);
|
||||
* var car = injector.get(Car);
|
||||
* expect(car instanceof Car).toBe(true);
|
||||
* expect(car.engine instanceof Engine).toBe(true);
|
||||
* ```
|
||||
*
|
||||
* Next we need to write the code that creates and instantiates the `Injector`. We then ask for the
|
||||
* `root` object, `Car`, so that the `Injector` can recursively build all of that object's
|
||||
*dependencies.
|
||||
*
|
||||
* ```javascript
|
||||
* main() {
|
||||
* var injector = Injector.resolveAndCreate([Car, Engine]);
|
||||
*
|
||||
* // Get a reference to the `root` object, which will recursively instantiate the tree.
|
||||
* var car = injector.get(Car);
|
||||
* }
|
||||
* ```
|
||||
* Notice that we don't use the `new` operator because we explicitly want to have the `Injector`
|
||||
* Notice, we don't use the `new` operator because we explicitly want to have the `Injector`
|
||||
* resolve all of the object's dependencies automatically.
|
||||
*/
|
||||
export class Injector {
|
||||
/**
|
||||
* Turns a list of binding definitions into an internal resolved list of resolved bindings.
|
||||
* Turns an array of binding definitions into an array of resolved bindings.
|
||||
*
|
||||
* A resolution is a process of flattening multiple nested lists and converting individual
|
||||
* bindings into a list of {@link ResolvedBinding}s. The resolution can be cached by `resolve`
|
||||
* for the {@link Injector} for performance-sensitive code.
|
||||
* A resolution is a process of flattening multiple nested arrays and converting individual
|
||||
* bindings into an array of {@link ResolvedBinding}s.
|
||||
*
|
||||
* @param `bindings` can be a list of `Type`, {@link Binding}, {@link ResolvedBinding}, or a
|
||||
* recursive list of more bindings.
|
||||
* ### Example ([live demo](http://plnkr.co/edit/AiXTHi?p=preview))
|
||||
*
|
||||
* The returned list is sparse, indexed by `id` for the {@link Key}. It is generally not useful to
|
||||
*application code
|
||||
* other than for passing it to {@link Injector} functions that require resolved binding lists,
|
||||
*such as
|
||||
* `fromResolvedBindings` and `createChildFromResolved`.
|
||||
* ```typescript
|
||||
* @Injectable()
|
||||
* class Engine {
|
||||
* }
|
||||
*
|
||||
* @Injectable()
|
||||
* class Car {
|
||||
* constructor(public engine:Engine) {}
|
||||
* }
|
||||
*
|
||||
* var bindings = Injector.resolve([Car, [[Engine]]]);
|
||||
*
|
||||
* expect(bindings.length).toEqual(2);
|
||||
*
|
||||
* expect(bindings[0] instanceof ResolvedBinding).toBe(true);
|
||||
* expect(bindings[0].key.displayName).toBe("Car");
|
||||
* expect(bindings[0].dependencies.length).toEqual(1);
|
||||
* expect(bindings[0].factory).toBeDefined();
|
||||
*
|
||||
* expect(bindings[1].key.displayName).toBe("Engine");
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* See {@link fromResolvedBindings} for more info.
|
||||
*/
|
||||
static resolve(bindings: Array<Type | Binding | any[]>): ResolvedBinding[] {
|
||||
return resolveBindings(bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves bindings and creates an injector based on those bindings. This function is slower than
|
||||
* the corresponding `fromResolvedBindings` because it needs to resolve bindings first. See
|
||||
*`resolve`
|
||||
* for the {@link Injector}.
|
||||
* Resolves an array of bindings and creates an injector from those bindings.
|
||||
*
|
||||
* Prefer `fromResolvedBindings` in performance-critical code that creates lots of injectors.
|
||||
* The passed-in bindings can be an array of `Type`, {@link Binding},
|
||||
* or a recursive array of more bindings.
|
||||
*
|
||||
* @param `bindings` can be a list of `Type`, {@link Binding}, {@link ResolvedBinding}, or a
|
||||
*recursive list of more
|
||||
* bindings.
|
||||
* @param `depProvider`
|
||||
* The method also takes an optional {@link DependencyProvider}, which is used to
|
||||
* resolve dependencies that cannot be expressed as bindings.
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/ePOccA?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* @Injectable()
|
||||
* class Engine {
|
||||
* }
|
||||
*
|
||||
* @Injectable()
|
||||
* class Car {
|
||||
* constructor(public engine:Engine) {}
|
||||
* }
|
||||
*
|
||||
* var injector = Injector.resolveAndCreate([Car, Engine]);
|
||||
* expect(injector.get(Car) instanceof Car).toBe(true);
|
||||
* ```
|
||||
*
|
||||
* This function is slower than the corresponding `fromResolvedBindings`
|
||||
* because it needs to resolve the passed-in bindings first.
|
||||
* See {@link resolve} and {@link fromResolvedBindings}.
|
||||
*/
|
||||
static resolveAndCreate(bindings: Array<Type | Binding | any[]>,
|
||||
depProvider: DependencyProvider = null): Injector {
|
||||
|
@ -472,12 +499,29 @@ export class Injector {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates an injector from previously resolved bindings. This bypasses resolution and flattening.
|
||||
* Creates an injector from previously resolved bindings.
|
||||
*
|
||||
* This API is the recommended way to construct injectors in performance-sensitive parts.
|
||||
*
|
||||
* @param `bindings` A sparse list of {@link ResolvedBinding}s. See `resolve` for the
|
||||
* {@link Injector}.
|
||||
* @param `depProvider`
|
||||
* The method also takes an optional {@link DependencyProvider}, which is used to
|
||||
* resolve dependencies that cannot be expressed as bindings.
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/KrSMci?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* @Injectable()
|
||||
* class Engine {
|
||||
* }
|
||||
*
|
||||
* @Injectable()
|
||||
* class Car {
|
||||
* constructor(public engine:Engine) {}
|
||||
* }
|
||||
*
|
||||
* var bindings = Injector.resolve([Car, Engine]);
|
||||
* var injector = Injector.fromResolvedBindings(bindings);
|
||||
* expect(injector.get(Car) instanceof Car).toBe(true);
|
||||
* ```
|
||||
*/
|
||||
static fromResolvedBindings(bindings: ResolvedBinding[],
|
||||
depProvider: DependencyProvider = null): Injector {
|
||||
|
@ -491,71 +535,128 @@ export class Injector {
|
|||
_isHost: boolean = false;
|
||||
_constructionCounter: number = 0;
|
||||
|
||||
constructor(public _proto: ProtoInjector, public _parent: Injector = null,
|
||||
/**
|
||||
* Private
|
||||
*/
|
||||
constructor(public _proto: any /* ProtoInjector */, public _parent: Injector = null,
|
||||
private _depProvider: DependencyProvider = null,
|
||||
private _debugContext: Function = null) {
|
||||
this._strategy = _proto._strategy.createInjectorStrategy(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns debug information about the injector.
|
||||
*
|
||||
* This information is included into exceptions thrown by the injector.
|
||||
* @private
|
||||
*/
|
||||
debugContext(): any { return this._debugContext(); }
|
||||
|
||||
/**
|
||||
* Retrieves an instance from the injector.
|
||||
* Retrieves an instance from the injector based on the provided token.
|
||||
* Throws {@link NoBindingError} if not found.
|
||||
*
|
||||
* @param `token`: usually the `Type` of an object. (Same as the token used while setting up a
|
||||
*binding).
|
||||
* @returns an instance represented by the token. Throws if not found.
|
||||
* ### Example ([live demo](http://plnkr.co/edit/HeXSHg?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* var injector = Injector.resolveAndCreate([
|
||||
* bind("validToken").toValue("Value")
|
||||
* ]);
|
||||
* expect(injector.get("validToken")).toEqual("Value");
|
||||
* expect(() => injector.get("invalidToken")).toThrowError();
|
||||
* ```
|
||||
*
|
||||
* `Injector` returns itself when given `Injector` as a token.
|
||||
*
|
||||
* ```typescript
|
||||
* var injector = Injector.resolveAndCreate([]);
|
||||
* expect(injector.get(Injector)).toBe(injector);
|
||||
* ```
|
||||
*/
|
||||
get(token: any): any {
|
||||
return this._getByKey(Key.get(token), null, null, false, Visibility.PublicAndPrivate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an instance from the injector.
|
||||
* Retrieves an instance from the injector based on the provided token.
|
||||
* Returns null if not found.
|
||||
*
|
||||
* @param `token`: usually a `Type`. (Same as the token used while setting up a binding).
|
||||
* @returns an instance represented by the token. Returns `null` if not found.
|
||||
* ### Example ([live demo](http://plnkr.co/edit/tpEbEy?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* var injector = Injector.resolveAndCreate([
|
||||
* bind("validToken").toValue("Value")
|
||||
* ]);
|
||||
* expect(injector.getOptional("validToken")).toEqual("Value");
|
||||
* expect(injector.getOptional("invalidToken")).toBe(null);
|
||||
* ```
|
||||
*
|
||||
* `Injector` returns itself when given `Injector` as a token.
|
||||
*
|
||||
* ```typescript
|
||||
* var injector = Injector.resolveAndCreate([]);
|
||||
* expect(injector.getOptional(Injector)).toBe(injector);
|
||||
* ```
|
||||
*/
|
||||
getOptional(token: any): any {
|
||||
return this._getByKey(Key.get(token), null, null, true, Visibility.PublicAndPrivate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an instance from the injector.
|
||||
*
|
||||
* @param `index`: index of an instance.
|
||||
* @returns an instance represented by the index. Throws if not found.
|
||||
* @private
|
||||
*/
|
||||
getAt(index: number): any { return this._strategy.getObjAtIndex(index); }
|
||||
|
||||
/**
|
||||
* Direct parent of this injector.
|
||||
* Parent of this injector.
|
||||
*
|
||||
* <!-- TODO: Add a link to the section of the user guide talking about hierarchical injection.
|
||||
* -->
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/eosMGo?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* var parent = Injector.resolveAndCreate([]);
|
||||
* var child = parent.resolveAndCreateChild([]);
|
||||
* expect(child.parent).toBe(parent);
|
||||
* ```
|
||||
*/
|
||||
get parent(): Injector { return this._parent; }
|
||||
|
||||
/**
|
||||
* @private
|
||||
* Internal. Do not use.
|
||||
*
|
||||
* We return `any` not to export the InjectorStrategy type.
|
||||
*/
|
||||
get internalStrategy(): any { return this._strategy; }
|
||||
|
||||
/**
|
||||
* Creates a child injector and loads a new set of bindings into it.
|
||||
*
|
||||
* A resolution is a process of flattening multiple nested lists and converting individual
|
||||
* bindings into a list of {@link ResolvedBinding}s. The resolution can be cached by `resolve`
|
||||
* for the {@link Injector} for performance-sensitive code.
|
||||
*
|
||||
* @param `bindings` can be a list of `Type`, {@link Binding}, {@link ResolvedBinding}, or a
|
||||
* recursive list of more bindings.
|
||||
* @param `depProvider`
|
||||
*/
|
||||
* Resolves an array of bindings and creates a child injector from those bindings.
|
||||
*
|
||||
* <!-- TODO: Add a link to the section of the user guide talking about hierarchical injection.
|
||||
* -->
|
||||
*
|
||||
* The passed-in bindings can be an array of `Type`, {@link Binding},
|
||||
* or a recursive array of more bindings.
|
||||
*
|
||||
* The methods also takes an optional {@link DependencyProvider}, which is used to
|
||||
* resolved dependencies that cannot be expressed as bindings.
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/opB3T4?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* class ParentBinding {}
|
||||
* class ChildBinding {}
|
||||
*
|
||||
* var parent = Injector.resolveAndCreate([ParentBinding]);
|
||||
* var child = parent.resolveAndCreateChild([ChildBinding]);
|
||||
*
|
||||
* expect(child.get(ParentBinding) instanceof ParentBinding).toBe(true);
|
||||
* expect(child.get(ChildBinding) instanceof ChildBinding).toBe(true);
|
||||
* expect(child.get(ParentBinding)).toBe(parent.get(ParentBinding));
|
||||
* ```
|
||||
*
|
||||
* This function is slower than the corresponding `createChildFromResolved`
|
||||
* because it needs to resolve the passed-in bindings first.
|
||||
* See {@link resolve} and {@link createChildFromResolved}.
|
||||
*/
|
||||
resolveAndCreateChild(bindings: Array<Type | Binding | any[]>,
|
||||
depProvider: DependencyProvider = null): Injector {
|
||||
var resolvedBindings = Injector.resolve(bindings);
|
||||
|
@ -563,12 +664,32 @@ export class Injector {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a child injector and loads a new set of {@link ResolvedBinding}s into it.
|
||||
* Creates a child injector from previously resolved bindings.
|
||||
*
|
||||
* @param `bindings`: A sparse list of {@link ResolvedBinding}s.
|
||||
* See `resolve` for the {@link Injector}.
|
||||
* @param `depProvider`
|
||||
* @returns a new child {@link Injector}.
|
||||
* <!-- TODO: Add a link to the section of the user guide talking about hierarchical injection.
|
||||
* -->
|
||||
*
|
||||
* This API is the recommended way to construct injectors in performance-sensitive parts.
|
||||
*
|
||||
* The methods also takes an optional {@link DependencyProvider}, which is used to
|
||||
* resolved dependencies that cannot be expressed as bindings.
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/VhyfjN?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* class ParentBinding {}
|
||||
* class ChildBinding {}
|
||||
*
|
||||
* var parentBindings = Injector.resolve([ParentBinding]);
|
||||
* var childBindings = Injector.resolve([ChildBinding]);
|
||||
*
|
||||
* var parent = Injector.fromResolvedBindings(parentBindings);
|
||||
* var child = parent.createChildFromResolved(childBindings);
|
||||
*
|
||||
* expect(child.get(ParentBinding) instanceof ParentBinding).toBe(true);
|
||||
* expect(child.get(ChildBinding) instanceof ChildBinding).toBe(true);
|
||||
* expect(child.get(ParentBinding)).toBe(parent.get(ParentBinding));
|
||||
* ```
|
||||
*/
|
||||
createChildFromResolved(bindings: ResolvedBinding[],
|
||||
depProvider: DependencyProvider = null): Injector {
|
||||
|
@ -582,8 +703,26 @@ export class Injector {
|
|||
/**
|
||||
* Resolves a binding and instantiates an object in the context of the injector.
|
||||
*
|
||||
* @param `binding`: either a type or a binding.
|
||||
* @returns an object created using binding.
|
||||
* The created object does not get cached by the injector.
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/yvVXoB?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* @Injectable()
|
||||
* class Engine {
|
||||
* }
|
||||
*
|
||||
* @Injectable()
|
||||
* class Car {
|
||||
* constructor(public engine:Engine) {}
|
||||
* }
|
||||
*
|
||||
* var injector = Injector.resolveAndCreate([Engine]);
|
||||
*
|
||||
* var car = injector.resolveAndInstantiate(Car);
|
||||
* expect(car.engine).toBe(injector.get(Engine));
|
||||
* expect(car).not.toBe(injector.resolveAndInstantiate(Car));
|
||||
* ```
|
||||
*/
|
||||
resolveAndInstantiate(binding: Type | Binding): any {
|
||||
return this.instantiateResolved(Injector.resolve([binding])[0]);
|
||||
|
@ -592,8 +731,25 @@ export class Injector {
|
|||
/**
|
||||
* Instantiates an object using a resolved binding in the context of the injector.
|
||||
*
|
||||
* @param `binding`: a resolved binding
|
||||
* @returns an object created using binding.
|
||||
* The created object does not get cached by the injector.
|
||||
*
|
||||
* ### Example ([live demo](http://plnkr.co/edit/ptCImQ?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* @Injectable()
|
||||
* class Engine {
|
||||
* }
|
||||
*
|
||||
* @Injectable()
|
||||
* class Car {
|
||||
* constructor(public engine:Engine) {}
|
||||
* }
|
||||
*
|
||||
* var injector = Injector.resolveAndCreate([Engine]);
|
||||
* var carBinding = Injector.resolve([Car])[0];
|
||||
* var car = injector.instantiateResolved(carBinding);
|
||||
* expect(car.engine).toBe(injector.get(Engine));
|
||||
* expect(car).not.toBe(injector.instantiateResolved(carBinding));
|
||||
*/
|
||||
instantiateResolved(binding: ResolvedBinding): any {
|
||||
return this._instantiateBinding(binding, Visibility.PublicAndPrivate);
|
||||
|
|
|
@ -3,10 +3,41 @@ import {CONST, CONST_EXPR, stringify, isBlank, isPresent} from "angular2/src/cor
|
|||
/**
|
||||
* A parameter metadata that specifies a dependency.
|
||||
*
|
||||
* ```
|
||||
* class AComponent {
|
||||
* constructor(@Inject(MyService) aService:MyService) {}
|
||||
* ### Example ([live demo](http://plnkr.co/edit/6uHYJK?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* class Engine {}
|
||||
*
|
||||
* @Injectable()
|
||||
* class Car {
|
||||
* engine;
|
||||
* constructor(@Inject("MyEngine") engine:Engine) {
|
||||
* this.engine = engine;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* var injector = Injector.resolveAndCreate([
|
||||
* bind("MyEngine").toClass(Engine),
|
||||
* Car
|
||||
* ]);
|
||||
*
|
||||
* expect(injector.get(Car).engine instanceof Engine).toBe(true);
|
||||
* ```
|
||||
*
|
||||
* When `@Inject()` is not present, {@link Injector} will use the type annotation of the parameter.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* ```typescript
|
||||
* class Engine {}
|
||||
*
|
||||
* @Injectable()
|
||||
* class Car {
|
||||
* constructor(public engine: Engine) {} //same as constructor(@Inject(Engine) engine:Engine)
|
||||
* }
|
||||
*
|
||||
* var injector = Injector.resolveAndCreate([Engine, Car]);
|
||||
* expect(injector.get(Car).engine instanceof Engine).toBe(true);
|
||||
* ```
|
||||
*/
|
||||
@CONST()
|
||||
|
@ -19,12 +50,21 @@ export class InjectMetadata {
|
|||
* A parameter metadata that marks a dependency as optional. {@link Injector} provides `null` if
|
||||
* the dependency is not found.
|
||||
*
|
||||
* ```
|
||||
* class AComponent {
|
||||
* constructor(@Optional() aService:MyService) {
|
||||
* this.aService = aService;
|
||||
* ### Example ([live demo](http://plnkr.co/edit/AsryOm?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* class Engine {}
|
||||
*
|
||||
* @Injectable()
|
||||
* class Car {
|
||||
* engine;
|
||||
* constructor(@Optional() engine:Engine) {
|
||||
* this.engine = engine;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* var injector = Injector.resolveAndCreate([Car]);
|
||||
* expect(injector.get(Car).engine).toBeNull();
|
||||
* ```
|
||||
*/
|
||||
@CONST()
|
||||
|
@ -64,16 +104,34 @@ export class DependencyMetadata {
|
|||
}
|
||||
|
||||
/**
|
||||
* A marker metadata that marks a class as available to `Injector` for creation. Used by tooling
|
||||
* for generating constructor stubs.
|
||||
* A marker metadata that marks a class as available to {@link Injector} for creation.
|
||||
*
|
||||
* ```
|
||||
* ### Example ([live demo](http://plnkr.co/edit/Wk4DMQ?p=preview))
|
||||
*
|
||||
* ```typescript
|
||||
* @Injectable()
|
||||
* class UsefulService {}
|
||||
*
|
||||
* @Injectable()
|
||||
* class NeedsService {
|
||||
* constructor(svc:UsefulService) {}
|
||||
* constructor(public service:UsefulService) {}
|
||||
* }
|
||||
*
|
||||
* @Injectable
|
||||
* var injector = Injector.resolveAndCreate([NeedsService, UsefulService]);
|
||||
* expect(injector.get(NeedsService).service instanceof UsefulService).toBe(true);
|
||||
* ```
|
||||
* {@link Injector} will throw {@link NoAnnotationError} when trying to instantiate a class that
|
||||
* does not have `@Injectable` marker, as shown in the example below.
|
||||
*
|
||||
* ```typescript
|
||||
* class UsefulService {}
|
||||
*
|
||||
* class NeedsService {
|
||||
* constructor(public service:UsefulService) {}
|
||||
* }
|
||||
*
|
||||
* var injector = Injector.resolveAndCreate([NeedsService, UsefulService]);
|
||||
* expect(() => injector.get(NeedsService)).toThrowError();
|
||||
* ```
|
||||
*/
|
||||
@CONST()
|
||||
|
@ -82,21 +140,32 @@ export class InjectableMetadata {
|
|||
}
|
||||
|
||||
/**
|
||||
* Specifies that an injector should retrieve a dependency from itself.
|
||||
* Specifies that an {@link Injector} should retrieve a dependency only from itself.
|
||||
*
|
||||
* ## Example
|
||||
* ### Example ([live demo](http://plnkr.co/edit/NeagAg?p=preview))
|
||||
*
|
||||
* ```
|
||||
* ```typescript
|
||||
* class Dependency {
|
||||
* }
|
||||
*
|
||||
* @Injectable()
|
||||
* class NeedsDependency {
|
||||
* constructor(public @Self() dependency:Dependency) {}
|
||||
* dependency;
|
||||
|
||||
* dependency;
|
||||
* constructor(@Self() dependency:Dependency) {
|
||||
* this.dependency = dependency;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* var inj = Injector.resolveAndCreate([Dependency, NeedsDependency]);
|
||||
* var nd = inj.get(NeedsDependency);
|
||||
* expect(nd.dependency).toBeAnInstanceOf(Dependency);
|
||||
*
|
||||
* expect(nd.dependency instanceof Dependency).toBe(true);
|
||||
*
|
||||
* var inj = Injector.resolveAndCreate([Dependency]);
|
||||
* var child = inj.resolveAndCreateChild([NeedsDependency]);
|
||||
* expect(() => child.get(NeedsDependency)).toThrowError();
|
||||
* ```
|
||||
*/
|
||||
@CONST()
|
||||
|
@ -107,28 +176,26 @@ export class SelfMetadata {
|
|||
/**
|
||||
* Specifies that the dependency resolution should start from the parent injector.
|
||||
*
|
||||
* ## Example
|
||||
* ### Example ([live demo](http://plnkr.co/edit/Wchdzb?p=preview))
|
||||
*
|
||||
*
|
||||
* ```
|
||||
* class Service {}
|
||||
*
|
||||
* class ParentService implements Service {
|
||||
* ```typescript
|
||||
* class Dependency {
|
||||
* }
|
||||
*
|
||||
* class ChildService implements Service {
|
||||
* constructor(public @SkipSelf() parentService:Service) {}
|
||||
* @Injectable()
|
||||
* class NeedsDependency {
|
||||
* dependency;
|
||||
* constructor(@SkipSelf() dependency:Dependency) {
|
||||
* this.dependency = dependency;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* var parent = Injector.resolveAndCreate([
|
||||
* bind(Service).toClass(ParentService)
|
||||
* ]);
|
||||
* var child = parent.resolveAndCreateChild([
|
||||
* bind(Service).toClass(ChildSerice)
|
||||
* ]);
|
||||
* var s = child.get(Service);
|
||||
* expect(s).toBeAnInstanceOf(ChildService);
|
||||
* expect(s.parentService).toBeAnInstanceOf(ParentService);
|
||||
* var parent = Injector.resolveAndCreate([Dependency]);
|
||||
* var child = parent.resolveAndCreateChild([NeedsDependency]);
|
||||
* expect(child.get(NeedsDependency).dependency instanceof Depedency).toBe(true);
|
||||
*
|
||||
* var inj = Injector.resolveAndCreate([Dependency, NeedsDependency]);
|
||||
* expect(() => inj.get(NeedsDependency)).toThrowError();
|
||||
* ```
|
||||
*/
|
||||
@CONST()
|
||||
|
@ -140,24 +207,59 @@ export class SkipSelfMetadata {
|
|||
* Specifies that an injector should retrieve a dependency from any injector until reaching the
|
||||
* closest host.
|
||||
*
|
||||
* ## Example
|
||||
* In Angular, a component element is automatically declared as a host for all the injectors in
|
||||
* its view.
|
||||
*
|
||||
* ```
|
||||
* class Dependency {
|
||||
* ### Example ([live demo](http://plnkr.co/edit/GX79pV?p=preview))
|
||||
*
|
||||
* In the following example `App` contains `ParentCmp`, which contains `ChildDirective`.
|
||||
* So `ParentCmp` is the host of `ChildDirective`.
|
||||
*
|
||||
* `ChildDirective` depends on two services: `HostService` and `OtherService`.
|
||||
* `HostService` is defined at `ParentCmp`, and `OtherService` is defined at `App`.
|
||||
*
|
||||
*```typescript
|
||||
* class OtherService {}
|
||||
* class HostService {}
|
||||
*
|
||||
* @Directive({
|
||||
* selector: 'child-directive'
|
||||
* })
|
||||
* class ChildDirective {
|
||||
* constructor(@Optional() @Host() os:OtherService, @Optional() @Host() hs:HostService){
|
||||
* console.log("os is null", os);
|
||||
* console.log("hs is NOT null", hs);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* class NeedsDependency {
|
||||
* constructor(public @Host() dependency:Dependency) {}
|
||||
* @Component({
|
||||
* selector: 'parent-cmp',
|
||||
* bindings: [HostService]
|
||||
* })
|
||||
* @View({
|
||||
* template: `
|
||||
* Dir: <child-directive></child-directive>
|
||||
* `,
|
||||
* directives: [ChildDirective]
|
||||
* })
|
||||
* class ParentCmp {
|
||||
* }
|
||||
*
|
||||
* var parent = Injector.resolveAndCreate([
|
||||
* bind(Dependency).toClass(HostDependency)
|
||||
* ]);
|
||||
* var child = parent.resolveAndCreateChild([]);
|
||||
* var grandChild = child.resolveAndCreateChild([NeedsDependency, Depedency]);
|
||||
* var nd = grandChild.get(NeedsDependency);
|
||||
* expect(nd.dependency).toBeAnInstanceOf(HostDependency);
|
||||
* ```
|
||||
* @Component({
|
||||
* selector: 'app',
|
||||
* bindings: [OtherService]
|
||||
* })
|
||||
* @View({
|
||||
* template: `
|
||||
* Parent: <parent-cmp></parent-cmp>
|
||||
* `,
|
||||
* directives: [ParentCmp]
|
||||
* })
|
||||
* class App {
|
||||
* }
|
||||
*
|
||||
* bootstrap(App);
|
||||
*```
|
||||
*/
|
||||
@CONST()
|
||||
export class HostMetadata {
|
||||
|
|
|
@ -6,7 +6,8 @@ import {
|
|||
StringWrapper,
|
||||
isString
|
||||
} from 'angular2/src/core/facade/lang';
|
||||
import {DependencyMetadata, resolveForwardRef} from 'angular2/src/core/di';
|
||||
import {resolveForwardRef} from 'angular2/src/core/di';
|
||||
import {DependencyMetadata} from 'angular2/src/core/di/metadata';
|
||||
|
||||
/**
|
||||
* Specifies that a constant attribute value should be injected.
|
||||
|
|
|
@ -4,12 +4,10 @@ import {describe, ddescribe, it, iit, expect, beforeEach} from 'angular2/test_li
|
|||
import {SpyDependencyProvider} from '../spies';
|
||||
import {
|
||||
Injector,
|
||||
ProtoInjector,
|
||||
bind,
|
||||
ResolvedBinding,
|
||||
Key,
|
||||
forwardRef,
|
||||
DependencyMetadata,
|
||||
Injectable,
|
||||
InjectMetadata,
|
||||
SelfMetadata,
|
||||
|
@ -17,12 +15,17 @@ import {
|
|||
SkipSelfMetadata,
|
||||
Optional,
|
||||
Inject,
|
||||
BindingWithVisibility,
|
||||
Visibility,
|
||||
Binding
|
||||
} from 'angular2/core';
|
||||
import {DependencyMetadata} from 'angular2/src/core/di/metadata';
|
||||
|
||||
import {InjectorInlineStrategy, InjectorDynamicStrategy} from 'angular2/src/core/di/injector';
|
||||
import {
|
||||
InjectorInlineStrategy,
|
||||
InjectorDynamicStrategy,
|
||||
ProtoInjector,
|
||||
BindingWithVisibility,
|
||||
Visibility
|
||||
} from 'angular2/src/core/di/injector';
|
||||
|
||||
class CustomDependencyMetadata extends DependencyMetadata {}
|
||||
|
||||
|
|
|
@ -115,9 +115,6 @@ const NG_API = [
|
|||
'BindingBuilder.toFactory',
|
||||
'BindingBuilder.toValue',
|
||||
|
||||
'BindingWithVisibility',
|
||||
'BindingWithVisibility.getKeyId',
|
||||
|
||||
'By', // TODO: not sure
|
||||
'By.all',
|
||||
'By.css',
|
||||
|
@ -351,6 +348,9 @@ const NG_API = [
|
|||
'DebugElement.queryAll',
|
||||
'DebugElement.triggerEventHandler',
|
||||
|
||||
'DependencyMetadata',
|
||||
'DependencyMetadata.token',
|
||||
|
||||
'DecimalPipe',
|
||||
'DecimalPipe.constructor',
|
||||
'DecimalPipe.transform',
|
||||
|
@ -370,8 +370,6 @@ const NG_API = [
|
|||
|
||||
'Dependency',
|
||||
'Dependency.fromKey',
|
||||
'DependencyMetadata',
|
||||
'DependencyMetadata.token',
|
||||
|
||||
'Directive',
|
||||
'Directive.constructor',
|
||||
|
@ -750,9 +748,6 @@ const NG_API = [
|
|||
|
||||
'PropertyMetadata',
|
||||
|
||||
'ProtoInjector',
|
||||
'ProtoInjector.getBindingAtIndex',
|
||||
|
||||
'ProtoViewRef',
|
||||
|
||||
'Query',
|
||||
|
@ -979,8 +974,6 @@ const NG_API = [
|
|||
'ViewRef.renderFragment',
|
||||
'ViewRef.setLocal',
|
||||
|
||||
'Visibility',
|
||||
|
||||
'WrappedException',
|
||||
'WrappedException.captureStackTrace',
|
||||
'WrappedException.constructor',
|
||||
|
|
Loading…
Reference in New Issue