web-dev-qa-db-ja.com

工場プロバイダーの使用方法は?

Angular 2アプリケーションの別のサービスにサービスを挿入する必要があります。

私が推論したドキュメントを読んだ後、最良のアプローチは Factory Provider を使用することです。ただし、次の2つの質問があります。

1)ドキュメントは、2つの「コードセグメント」を持つHeroServiceProviderクラスの作成を推奨しています。

let heroServiceFactory = (logger: Logger, userService: UserService) => {
  return new HeroService(logger, userService.user.isAuthorized);
};

export let heroServiceProvider =
  { provide: HeroService,
    useFactory: heroServiceFactory,
    deps: [Logger, UserService]
  };

私の質問は、クラスが一般的にどのように見えるかです。上記のコードセグメントはどこに追加する必要がありますか?

2)この工場をどのように使用するか、または使用できますか?次のようにインポートする必要があります。

import { heroServiceProvider } from './hero.service.provider';

@Component({
  selector: 'my-selector',
  template: `
  `,
  providers: [heroServiceProvider]
})

目的のパラメータ化されたサービスを取得してアクセスするにはどうすればよいですか?

10
arjacsoh

長い検索の後、私はapp_initalizerに注入するのと同じ問題に直面しました、私は以下の解決策を見つけました。これがあなたのシナリオの助けになるかもしれません。

@NgModule({
  imports: [ BrowserModule],
  ...
  providers: [
    {
      provide: HeroService,
      useFactory: heroServiceFactory,
      deps: [Logger, UserService],
      multi: true
    }
    ]
})
export class AppModule {}


export function heroServiceFactory = (logger: Logger, userService: UserService) => {
    return new HeroService(logger, userService.user.isAuthorized);
};
16

@mgmgの回答に対してコメントするのに十分なポイントがありませんが、ここに役立つ情報があります...

私は自分のアプリでドキュメント(およびこの質問の主題)に記載されているプロバイダーファクトリパターンを使用しましたが、コンパイルでエラーが発生し続けました

シンボル値を静的に解決中にエラーが発生しました。関数呼び出しはサポートされていません。関数またはラムダをエクスポートされた関数への参照に置き換えることを検討してください...

本質的に、ファクトリ依存関係がルートモジュールで使用される場合、すべての依存関係を提供する必要があります。

つまり、@mgmgの回答で指定されたコードブロックには、厳密に依存サービスが必要です。

import { heroServiceProvider } from './hero.service.provider';
import { UserService } from './user.service';
import { Logger }      from './logger.service';

...

@NgModule({

  ...

  providers: [
    Logger,
    UserService,
    heroServiceProvider
    // Wrapper for:
    //{ provide: HeroService,
    //  useFactory: (logger: Logger, userService: UserService) => {
    //    return new HeroService(logger, userService.user.isAuthorized)
    //  },
    //  deps: [Logger, UserService]
    //};

  ],
  bootstrap: [ AppComponent ]
})

注:angular docs hereheroServiceProviderheroes.componentapp.moduleにはなく、LoggerとUserServiceへの参照は不要ですこれら2つの依存関係は、インジェクターツリーの上位から取得されていると思います。

2
Richard Matsen

1)質問の最初の部分は簡単です:質問に示すように、提供したスニペットを別のファイルに保持し、コンポーネントにインポートするだけです:

import { heroServiceProvider } from './hero.service.provider';

2)実際の使用に関しては、コンポーネントのサービス関連のコードを実際に変更する必要はありません。元のサービスが注入された場合はそのまま使用し続けます。コンポーネントコンストラクターを変更する必要さえありません。サービスプロバイダーの考え方は、コンポーネントごとにカスタムサービスプロバイダーを用意することで、コンポーネントごとにサービスをカスタマイズでき、ファクトリー関数でコンポーネント固有の初期化を行うことです。コンポーネントのデコレータにサービスプロバイダーをリストすることを忘れないでください。Angularは残りを「自動的に」処理します。

1
Anton Nikiforov

質問1:
クラスは一般的にどのように見えるべきですか?上記のコードセグメントはどこに追加する必要がありますか?

回答:
ヒーローサービスプロバイダーとそのファクトリー機能のコードを含むファイルを作成できます。このファイルには、hero.service.provider.tsという名前を付けることができます。
そして、ヒーローサービスのコードをhero.service.tsという名前の別のファイルに記述します。

他の例を参照するには、 Angular Service Providers の使用方法についての記事をご覧ください。

hero.service.provider.tsファイル:

import { HeroService } from './hero.service';
import { Logger } from './logger.service';
import { UserService } from './user.service';

let heroServiceFactory = (logger: Logger, userService: UserService) => {
  return new HeroService(logger, userService.user.isAuthorized);
};

export let heroServiceProvider =
  { provide: HeroService,
    useFactory: heroServiceFactory,
    deps: [Logger, UserService]
  };

質問2:このファクトリーをどのように使用するべきですか?

回答:
提供したサンプルコードに従って、@Componentデコレーターのプロバイダーフィールドを使用してサービス用にファクトリーを構成し、 サービスを挿入できます クラスコンストラクターまたはAngularインジェクターオブジェクトを使用。

ただし、工場のプロバイダーがこの方法で構成した場合、ツリーの揺れは機能しません。木の揺れが必要な場合は、この Angular tree Shakable Serviceの例をご覧ください

import { heroServiceProvider } from './hero.service.provider';
import { HeroService } from './hero.service';

@Component({
  selector: 'my-selector',
  template: ``,
  providers: [heroServiceProvider]
})
export class HeroComponent {
  constructor(private heroService: HeroService) { } 
}
1
Jun711

今日、私は同じ質問に直面し、解決策を見つけました。

1)angular.ioで正確なコードを見つけました。次を参照してください。 https://github.com/angular/angular.io/blob/master/public/docs/_examples/dependency-injection/ts/src /app/heroes/hero.service.provider.ts (2017年3月15日に更新されたリンク)。
このコードから、heroServiceProviderはクラスである必要はありません。

2)app.module.tsでは、@ NgModuleにproviderプロパティがあります。そして、次のようにheroServiceProviderを追加できます:

import { heroServiceProvider } from './hero.service.provider';

...

@NgModule({

  ...

  providers: [
    heroServiceProvider
  ],
  bootstrap: [ AppComponent ]
})

そのような@NgModuleでサービスを提供することにより、アプリケーションスコープでサービスを使用できます。

0
mgmg