Angular(6.0.7
)そして、新しいサービスを作成しようとしています:
@Injectable({
providedIn: 'root'
})
しかし、インターフェイスでどのように注入を入力できますか?
問題
2つのサービス、Authentication.serviceおよびSessionStorage.serviceがあります。セッションストレージを認証サービスに注入したい。それは次の方法で実行できます。
constructor(private sessionStorage: SessionStorage) {
}
問題ありません。しかし、オブジェクト指向の目的のために、このサービスの上にinterface
が必要です(両方のlocalstorageサービスをsessionstorageサービスとして実装できるようにするため)。したがって、注入されたクラスをインターフェイスで入力したいのは論理的ですが、これは同じ方法で行うことはできません Angular 5以下はそれを行います 。
それでは、このグローバルサービスにインターフェイスでインジェクションを入力するにはどうすればよいですか?
試した
AngularサービスタイピングはInjectableProvider
を記述しますが、これはInjectableProvider
の兄弟のパラメータのいずれとも一致しないため、コンパイラ(およびtslint )エラー。
@Injectable({
providedIn: 'root'
}, {provide: IStorageService, useClass: SessionStorage})
これは、廃止されたInjectionToken
の代わりに使用されるOpaqueToken
で実行できます。
export const AuthenticationProvider = new InjectionToken(
"AuthenticationProvider",
{ providedIn: "root", factory: () => new CognitoAuthenticationProvider() }
);
...
@Injectable()
export class CognitoAuthenticationProvider implements IAuthenticationProvider {
...
@Injectable({
providedIn: "root"
})
export class AuthenticationService {
constructor(
@Inject(AuthenticationProvider)
private authenticationProvider: IAuthenticationProvider,
private http: HttpClient
) {}
これを解決するために次のようなものを使用しました
app.module.ts
providers: [
{ provide: AlmostInterface, useClass: environment.concrete }
...
]
AlmostInterface.ts
export abstract class AlmostInterface {
abstract myMethod();
}
MyConcrete.ts
export class MyConcrete implements AlmostInterface {
myMethod() { ... }; // implementation
}
export class MyConcreteAlternative implements AlmostInterface {
myMethod() { ... }; // implementation
}
environment.ts
export const environment = {
production: false,
concrete: MyConcreteAlternative
};
environment.prod.ts
export const environment = {
production: true,
concrete: MyConcrete
};
実行時にはTypeScriptインターフェイスは存在しないため(コンパイル時の型安全性のみ)、依存性注入にTypeScriptインターフェイスを使用できないと思います。
抽象クラスを使用することをお勧めします。
編集:@InjectableのfirstパラメーターでuseClass
を使用できるようです。例のように秒として使用することはできません。それを@ k0zakinioの回答と組み合わせると、次のようになります。
@Injectable({
providedIn: 'root',
useClass: environment.concrete,
deps: []
})
export abstract class SessionStorage { }
また、deps
またはinject
を介して依存関係を宣言する必要があるようです。これを確認してください github issue 。今回の回答がもっと役立つことを願っています。
次のようなものを使用できます-
[{ provide: InterfaceName, useClass: ClassName}]