248 lines
6.1 KiB
TypeScript
248 lines
6.1 KiB
TypeScript
/**
|
|
* @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 {stringify} from '../facade/lang';
|
|
|
|
/**
|
|
* A parameter metadata that specifies a dependency.
|
|
*
|
|
* ### 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([
|
|
* {provide: "MyEngine", useClass: 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);
|
|
* ```
|
|
* @stable
|
|
*/
|
|
export class InjectMetadata {
|
|
constructor(public token: any) {}
|
|
toString(): string { return `@Inject(${stringify(this.token)})`; }
|
|
}
|
|
|
|
/**
|
|
* A parameter metadata that marks a dependency as optional. {@link Injector} provides `null` if
|
|
* the dependency is not found.
|
|
*
|
|
* ### 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();
|
|
* ```
|
|
* @stable
|
|
*/
|
|
export class OptionalMetadata {
|
|
toString(): string { return `@Optional()`; }
|
|
}
|
|
|
|
/**
|
|
* `DependencyMetadata` is used by the framework to extend DI.
|
|
* This is internal to Angular and should not be used directly.
|
|
* @stable
|
|
*/
|
|
export class DependencyMetadata {
|
|
get token(): any { return null; }
|
|
}
|
|
|
|
/**
|
|
* 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(public service:UsefulService) {}
|
|
* }
|
|
*
|
|
* 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();
|
|
* ```
|
|
* @stable
|
|
*/
|
|
export class InjectableMetadata {
|
|
constructor() {}
|
|
}
|
|
|
|
/**
|
|
* Specifies that an {@link Injector} should retrieve a dependency only from itself.
|
|
*
|
|
* ### Example ([live demo](http://plnkr.co/edit/NeagAg?p=preview))
|
|
*
|
|
* ```typescript
|
|
* class Dependency {
|
|
* }
|
|
*
|
|
* @Injectable()
|
|
* class NeedsDependency {
|
|
* dependency;
|
|
* constructor(@Self() dependency:Dependency) {
|
|
* this.dependency = dependency;
|
|
* }
|
|
* }
|
|
*
|
|
* var inj = Injector.resolveAndCreate([Dependency, NeedsDependency]);
|
|
* var nd = inj.get(NeedsDependency);
|
|
*
|
|
* expect(nd.dependency instanceof Dependency).toBe(true);
|
|
*
|
|
* var inj = Injector.resolveAndCreate([Dependency]);
|
|
* var child = inj.resolveAndCreateChild([NeedsDependency]);
|
|
* expect(() => child.get(NeedsDependency)).toThrowError();
|
|
* ```
|
|
* @stable
|
|
*/
|
|
export class SelfMetadata {
|
|
toString(): string { return `@Self()`; }
|
|
}
|
|
|
|
/**
|
|
* Specifies that the dependency resolution should start from the parent injector.
|
|
*
|
|
* ### Example ([live demo](http://plnkr.co/edit/Wchdzb?p=preview))
|
|
*
|
|
* ```typescript
|
|
* class Dependency {
|
|
* }
|
|
*
|
|
* @Injectable()
|
|
* class NeedsDependency {
|
|
* dependency;
|
|
* constructor(@SkipSelf() dependency:Dependency) {
|
|
* this.dependency = dependency;
|
|
* }
|
|
* }
|
|
*
|
|
* 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();
|
|
* ```
|
|
* @stable
|
|
*/
|
|
export class SkipSelfMetadata {
|
|
toString(): string { return `@SkipSelf()`; }
|
|
}
|
|
|
|
/**
|
|
* Specifies that an injector should retrieve a dependency from any injector until reaching the
|
|
* closest host.
|
|
*
|
|
* In Angular, a component element is automatically declared as a host for all the injectors in
|
|
* its view.
|
|
*
|
|
* ### 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);
|
|
* }
|
|
* }
|
|
*
|
|
* @Component({
|
|
* selector: 'parent-cmp',
|
|
* providers: [HostService],
|
|
* template: `
|
|
* Dir: <child-directive></child-directive>
|
|
* `,
|
|
* directives: [ChildDirective]
|
|
* })
|
|
* class ParentCmp {
|
|
* }
|
|
*
|
|
* @Component({
|
|
* selector: 'app',
|
|
* providers: [OtherService],
|
|
* template: `
|
|
* Parent: <parent-cmp></parent-cmp>
|
|
* `,
|
|
* directives: [ParentCmp]
|
|
* })
|
|
* class App {
|
|
* }
|
|
*
|
|
* bootstrap(App);
|
|
*```
|
|
* @stable
|
|
*/
|
|
export class HostMetadata {
|
|
toString(): string { return `@Host()`; }
|
|
}
|