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 injectable-not-always-needed-in-ts //- The [Angular 2 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-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')