extends ../../../ts/_cache/guide/dependency-injection.jade block includes include ../_util-fns - var _thisDot = ''; block ctor-syntax .l-sub-section :marked We also leveraged Dart's constructor syntax for declaring parameters and initializing properties simultaneously. block register-provider-ngmodule :marked Before we do, let's see an example of provider registration during bootstrapping: +makeExcerpt('app/main.1.ts (discouraged)', 'bootstrap-discouraged', '') :marked The injector now knows about our `HeroService`. An instance of our `HeroService` will be available for injection across our entire application. Of course we can't help wondering about that comment telling us not to do it this way. It *will* work. It's just not a best practice. The bootstrap provider option is intended for configuring and overriding Angular's own preregistered services, such as its routing support. The preferred approach is to register application providers in application components. Because the `HeroService` is used within the *Heroes* feature area — and nowhere else — the ideal place to register it is in the top-level `HeroesComponent`. block ngmodule-vs-component :marked Look at the `providers` part of the `@Component` annotation. An instance of the `HeroService` is now available for injection in this `HeroesComponent` and all of its child components. The `HeroesComponent` itself doesn't happen to need the `HeroService`. But its child `HeroListComponent` does, so we head there next. block injectable-not-always-needed-in-ts //- The [Angular Dart Transformer](https://github.com/angular/angular/wiki/Angular-2-Dart-Transformer) //- generates static code to replace the use of dart:mirrors. It requires that types be //- identified as targets for static code generation. Generally this is achieved //- by marking the class as @Injectable (though there are other mechanisms). block always-include-paren :marked Always write `@Injectable()`, not just `@Injectable`. A metadata annotation must be either a reference to a compile-time constant variable or a call to a constant constructor such as `Injectable()`. If we forget the parentheses, the analyzer will complain: "Annotation creation must have arguments". If we try to run the app anyway, it won't work, and the console will say "expression must be a compile-time constant". block real-logger .l-sub-section :marked A real implementation would probably use the [logging package](https://pub.dartlang.org/packages/logging). block provider-shorthand :marked This is actually a shorthand expression for a provider registration that creates a new instance of the [Provider](../api/angular2.core/Provider-class.html) class: block provider-ctor-args - var _secondParam = 'named parameter, such as useClass' :marked We supply two arguments (or more) to the `Provider` constructor. block dart-diff-const-metadata .callout.is-helpful header Dart difference: Constants in metadata :marked In Dart, the value of a metadata annotation must be a compile-time constant. For that reason, we can't call functions to get values to use within an annotation. Instead, we use constant literals or constant constructors. For example, a TypeScript program will use the object literal `{ provide: Logger, useClass: BetterLogger }`. A Dart annotation would instead use the constant value `const Provider(Logger, useClass: BetterLogger)`. block dart-diff-const-metadata-ctor .callout.is-helpful header Dart difference: Constants in metadata :marked Because Dart annotations must be compile-time constants, `useValue` is often used with string or list literals. However, `useValue` works with any constant object. To create a class that can provide constant objects, ensure all its instance variables are `final`, and give it a `const` constructor. Create a constant instance of the class by using `const` instead of `new`. // - var stylePattern = { otl: /(useValue.*\))/gm }; // +makeExample('dependency-injection/dart/lib/providers_component.dart','providers-9','', stylePattern)(format='.') block non-class-dep-eg span string, list, map, or maybe a function. block config-obj-maps | . They can be | Map | literals block what-should-we-use-as-token :marked But what should we use as the token? While we _could_ use **[Map][]**, we _should not_ because (like `String`) `Map` is too general. Our app might depend on several maps, each for a different purpose. [Map]: https://api.dartlang.org/stable/dart-core/Map-class.html .callout.is-helpful header Dart difference: Interfaces are valid tokens :marked In TypeScript, interfaces don't work as provider tokens. Dart doesn't have this limitation; every class implicitly defines an interface, so interface names are just class names. `Map` is a *valid* token even though it's the name of an abstract class; it's just *unsuitable* as a token because it's too general. block dart-map-alternative :marked As an alternative to using a configuration `Map`, we can define a custom configuration class: +makeExcerpt('lib/app_config.dart (alternative config)','config-alt') :marked Defining a configuration class has a few benefits. One key benefit is strong static checking: we'll be warned early if we misspell a property name or assign it a value of the wrong type. The Dart [cascade notation][cascade] (`..`) provides a convenient means of initializing a configuration object. If we use cascades, the configuration object can't be declared `const` and we can't use a [value provider](#value-provider). A solution is to use a [factory provider](#factory-provider). We illustrate this next. We also show how to provide and inject the configuration object in our top-level `AppComponent`: [cascade]: https://www.dartlang.org/docs/dart-up-and-running/ch02.html#cascade +makeExcerpt('lib/app_component.dart','providers') +makeExcerpt('lib/app_component.dart','ctor')