extends ../../../ts/latest/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 service-in-its-own-file
  //- N/A

block one-class-per-file-ts-tradeoffs
  //- N/A

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 ts-any-decorator-will-do
  //- N/A

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 canonical-provider-expr
  | &nbsp;that creates a new instance of the&nbsp;
  a(href="../api/core/Provider-class.html") Provider
  | &nbsp;class:

block provider-ctor-args
  - var _secondParam = 'named parameter, such as <code>useClass</code>' 
  :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 
  | <b><a href="https://api.dartlang.org/stable/dart-core/Map-class.html">Map</a></b>
  | 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:

  +makeExample('dependency-injection/ts/app/app.config.ts','config-alt','app/app-config.ts (alternative config)')(format='.')

  :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')
