web-dev-qa-db-ja.com

コンストラクターパラメーターを必要とするサービスを記述する方法

MetricsServiceサービスを宣言するコンポーネントがあります。このサービスには、HttpModuleと、使用するホストおよび認証キーを定義する2つのstringsの両方が必要です。

メトリックサービスは次のとおりです。

@Injectable()
export class MetricsService {
    constructor(
        private http: Http,
        public wsAuthKey: string,
        public wsHost: string
        ) {
        this.wsAuthKey  = wsAuthKey || "blahblahblahblahblahblahblahblah=";
        this.wsHost     = wsHost    || "https://preprod-admin.myservice.ws";
    }

それを使用するコンポーネントは次のように書かれています。

export class DatavizComponent implements OnInit, OnChanges {
    constructor(
        private zms: MetricsService,
    ) { 
    }

私の質問は、ホストとキーを渡すことを含む(ただし、httpは渡さない)全体が機能するように、コンポーネントコンストラクターをどのように記述するかです。

注:現在作成されているコードはコンパイルされません。

より正確には、コンポーネントがアプリ依存のデータを次のように提供することを期待します。

 export class DatavizComponent implements OnInit, OnChanges {
        constructor(
            private zms = MetricsService("http://myhost.com", "mykey"),
        ) { 
        }

しかし、これが機能する場合、httpを渡す方法は?

提案されたソリューションの後の更新:

export class MetricsService {

    constructor(
        private http: Http,
        @Inject('wsAuthKey') @Optional() public wsAuthKey?: string,
        @Inject('wsHost') @Optional() public wsHost?: string
        ) {
        this.wsAuthKey  = wsAuthKey || "blahblah=";
        this.wsHost     = wsHost    || "https://preprod-admin.Host.ws";


        console.log("MetricsService constructor="
            + " wsAuthKey="+this.wsAuthKey
            + ", wsHost="+this.wsHost
        );

    }

コンポーネント内:

@Component({
    selector:    'dataviz-offers-volumes',
    templateUrl: 'app/dataviz.component.html',
    styleUrls:  ['app/dataviz.component.css'],
    encapsulation: ViewEncapsulation.None,
    providers: [
        {provide: 'wsAuthKey',  useValue: 'abc'}, 
        {provide: 'wsHost',     useValue: 'efg'}, 
    ],
})
export class DatavizComponent implements OnInit, OnChanges {

    @ViewChild('chart') private chartContainer: ElementRef;
    @Input() private graphId:string;
    @Input() private wsAuthKey:string;
    @Input() private wsHost:string;
    @Input() private maxSamples=12;

    constructor(
        private zms: MetricsService
    ) { 
    }

コンストラクターでは、ログは次のとおりです(値は渡されません)。

MetricsService constructor= wsAuthKey=blahblah=, wsHost=https://preprod-admin.Host.ws

「abc」と「efg」が表示されるはずです。

しかし、dataviz componenetを使用するコンポーネントに問題はないのでしょうか。このコンポーネントでは、次の情報が渡されました。

@Input() private wsAuthKey:string;
@Input() private wsHost:string;

タグでオプションでホストとキーをプリセットしたいので:

                <h1>dataviz volume</h1>
                <div class="chartContainer left" title="Simultaneous offers via dataviz directive">
                    <dataviz-offers-volumes 
                        id="dataviz-volumes1"
                        [graphId]="graphId"
                        [wsAuthKey]="'myauthkey'"
                        [wsHost]="'http://myhost.com'"
                        [maxSamples]="123"
                    >
                    </dataviz-offers-volumes>
                </div>
22

パラメーターをオプションにするには、@Optional()(DI)および_?_(TypeScript)、およびプロバイダーキーとしてサポートされていないプリミティブ値の@Inject(somekey)を追加します。

_@Injectable()
export class MetricsService {
    constructor(
        private http: Http,
        @Inject('wsAuthKey') @Optional() public wsAuthKey?: string,
        @Inject('wsHost') @Optional() public wsHost?: string
        ) {
        this.wsAuthKey  = wsAuthKey || "blahblahblahblahblahblahblahblah=";
        this.wsHost     = wsHost    || "https://preprod-admin.myservice.ws";
    }
_
_providers: [
  {provide: 'wsAuthKey', useValue: 'abc'}, 
  {provide: 'wsHost', useValue: 'efg'}, 
]
_

指定された場合は渡され、そうでない場合は無視されますが、DIは依然としてMetricsServiceを挿入できます。

32

これは、特に この質問 で説明されている一般的なレシピです。設定を保持するサービスである必要があります。

@Injectable()
export class MetricsConfig {
  wsAuthKey = "blahblahblahblahblahblahblahblah=";
  wsHost = "https://preprod-admin.myservice.ws";
}

@Injectable()
export class MetricsService {
    constructor(
        private http: Http,
        metricsConfig: MetricsConfig
    ) {
        this.wsAuthKey  = metricsConfig.wsAuthKey;
        this.wsHost     = metricsConfig.wsHost;
    }
}

変更する必要がある場合は、モジュール全体または特定のコンポーネントに対してオーバーライドまたは拡張できます。

@Component(
  ...
  { provide: MetricsConfig, useClass: class ExtendedMetricsConfig { ... } }
)
export class DatavizComponent ...

この場合、MetricsConfigをクラスにする必要はありません。 OpaqueToken値プロバイダーでもあります。しかし、クラスは便利に拡張することができ、注入するのが簡単で、すでに入力用のインターフェースを提供しています。

13
Estus Flask

公式ドキュメントから: https://angular.io/guide/dependency-injection-in-action#injectiontoken

コンストラクターで@Optionalデコレーターを使用します。

export class MyService {
  constructor( @Optional() public var: type = value ) { }
}
0
Gus