Я пытаюсь создать фабрику услуг для службы кэширования. Основное требование состоит в том, что один сервис может быть каждый раз создан с другой строкой.
В конечном результате будет несколько служб кэширования, каждая из которых определяется уникальным databaseName
. В каждом кэше может быть одно или несколько хранилищ, также определяемых уникальным storeName
. Другие сервисы смогут использовать эти магазины:
mainCache = new Cache('main')
├── userStore = new Store(mainCache, 'user')
│ ├── userService
│ └── authenticationService
│
└── taskStore = new Store(mainCache, 'task')
└── taskService
fooCache = new Cache('foo')
└── barStore = new Store(otherCache, 'bar')
Мои текущие реализации выглядят так:
//indexeddb-cache.ts
import { Injectable } from '@angular/core';
@Injectable()
export class IndexedDBCache {
constructor(
protected databaseName : string
) {}
}
// indexeddb-store.ts
import { Injectable } from '@angular/core';
import { IndexedDBCache } from './indexeddb-cache';
@Injectable()
export class IndexedDBStore {
constructor(
protected database : IndexedDBCache,
protected storeName : string
) {}
}
Услуги фабричные:
// test-api.cache.factory.ts
import { IndexedDBCache } from '../indexeddb-cache/indexeddb-cache';
import { IndexedDBStore } from '../indexeddb-cache/indexeddb-store';
// factory functions for FactoryProviders as exports instead of inline:
// https://github.com/rangle/angular-2-aot-sandbox#func-in-providers-usefactory-top
export function mainIndexedDBCacheFactory() { return new IndexedDBCache('main'); }
export function userIndexedDBStoreFactory(testIndexedDBCache: IndexedDBCache) { return new IndexedDBStore(testIndexedDBCache, 'user'); }
export function taskIndexedDBStoreFactory(testIndexedDBCache: IndexedDBCache) { return new IndexedDBStore(testIndexedDBCache, 'task'); }
А затем предоставил:
// test-api.cache.ts
import { InjectionToken, Provider } from '@angular/core';
import { IndexedDBCache } from '../indexeddb-cache/indexeddb-cache';
import { IndexedDBStore } from '../indexeddb-cache/indexeddb-store';
import { mainIndexedDBCacheFactory,
taskIndexedDBStoreFactory,
userIndexedDBStoreFactory } from './test-api.cache.factory';
// Caches
export const mainIndexedDBCache = new InjectionToken<IndexedDBCache>('mainIndexedDBCache');
export let mainIndexedDBCacheProvider : Provider = {
provide: mainIndexedDBCache,
useFactory: mainIndexedDBCacheFactory
};
// Stores
export const userIndexedDBStore = new InjectionToken<IndexedDBStore>('userIndexedDBStore');
export let userIndexedDBStoreProvider : Provider = {
provide: userIndexedDBStore, deps: [mainIndexedDBCache],
useFactory: userIndexedDBStoreFactory
};
export const taskIndexedDBStore = new InjectionToken<IndexedDBStore>('taskIndexedDBStore');
export let taskIndexedDBStoreProvider : Provider = {
provide: taskIndexedDBStore, deps: [mainIndexedDBCache],
useFactory: taskIndexedDBStoreFactory
};
Объявлено в основном модуле:
// test-api-module.ts
import { NgModule, ModuleWithProviders } from '@angular/core';
import { mainIndexedDBCacheProvider,
taskIndexedDBStoreProvider,
userIndexedDBStoreProvider } from './test-api.cache';
@NgModule({
imports: [], declarations: [], exports: []
})
export class TestAPIModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: TestAPIModule,
providers: [
mainIndexedDBCacheProvider,
userIndexedDBStoreProvider,
taskIndexedDBStoreProvider
]
};
}
}
И, наконец, используется в сервисе:
//user-service/user.service.ts
import { Inject, Injectable } from '@angular/core';
import { IndexedDBStore } from '../../indexeddb-cache/indexeddb-store';
import { userIndexedDBStore } from '../test-api.cache';
@Injectable()
export class UserService {
constructor(
@Inject(userIndexedDBStore) protected cache : IndexedDBStore
) {}
}
Все отлично работает при использовании JIT-компиляторов. Когда я пытаюсь выполнить компиляцию AoT, я начинаю получать Warning: Can't resolve all parameters for x in y: (?). This will become an error in Angular v5.x
для строковых параметров службы кеша и хранилища.
Я уже подробно описывал свою проблему в этом вопросе: Токенизация для компиляции AoT. Теперь похоже, что использование строк в качестве параметров для @Injectable()
совершенно невозможно с компилятором AoT. Есть ли другой способ создать фабрику для служб, инициализированных с помощью строки, как я описал?
Я создал рабочий пример в этом репозитории. Проверьте ветку aot
, и npm install
, за которой следует npm run build.prod.rollup.aot
, должны работать точно так же.
IndexedDBCache
и местонахождениеindexeddb-cache.ts
. - person Raven   schedule 09.06.2017protected storeName : string
. Нетstring
провайдера. Это не специфичная для AoT функция, я ожидаю, что она потерпит неудачу и в JiT, потому что это просто неправильно. Если вы используетеIndexedDBCache
только какnew IndexedDBCache
, это не должно бытьInjectable
. Попробуйте удалитьInjectable
из классов, которые не выполняют DI в конструкторах, и проверьте, работает ли это для вас. - person Estus Flask   schedule 09.06.2017