创建兼容AoT的服务工厂 [英] Creating AoT compatible Service Factories
问题描述
我正在尝试为缓存服务创建服务工厂。主要要求是单个服务每次都可以使用不同的字符串进行实例化。
I'm trying to create a service factory for a caching service. The major requirement is that a single service can be instanced with a different string each time.
最终结果将具有多个每个定义的 cache 服务通过唯一的 databaseName
。每个缓存可以具有一个或多个商店,它们也由唯一的 storeName
定义。其他服务将可以使用这些存储:
The final result will have multiple cache services each defined by a unique databaseName
. Each cache can have one or more stores also defined by a unique storeName
. Other services will be able to use these stores:
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')
我当前的实现如下所示:
My current implementations look like this:
//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编译时,我开始收到警告:无法解析y中的x的所有参数:(?)。对于缓存和存储服务的字符串参数,这将成为Angular v5.x中的错误
。
Everything works fine when using JIT compilers. When I'm trying to do AoT compilation I start receiving Warning: Can't resolve all parameters for x in y: (?). This will become an error in Angular v5.x
for the string parameters of the cache and store service.
我之前已经详细介绍了我的问题在这个问题中:为AoT编译进行标记化。现在看来,使用AoT编译器完全不可能将字符串用作 @Injectable()
的参数。如我所述,还有其他方法可以为使用字符串初始化的服务创建工厂吗?
I've detailed my issue before in this question: Tokenizing for AoT compilation. Now it looks like using strings as parameters for an @Injectable()
is completely impossible with the AoT compiler. Is there any other way of creating a factory for services initialized using a string as I've described?
我已经在此存储库。检出 aot
分支和 npm install
,然后执行 npm运行build.prod.rollup.aot
应该就是这样。
I've created a workable example in this repository. Checkout the aot
branch and npm install
followed by npm run build.prod.rollup.aot
should work just like that.
推荐答案
根据用户@estus和@Toxicable只能由 Factory
实例化的类本身不应为 @Injectable
本身。从 IndexedDBCache
和 IndexedDBStore
类中删除此标记将解决此问题。
Based on feedback from users @estus and @Toxicable the class that will only be instanced by a Factory
should not be @Injectable
itself. Removing this tag from the IndexedDBCache
and IndexedDBStore
classes will resolve the issue.
工厂
也必须采用特定形式
export function mainIndexedDBCacheFactory() { return new IndexedDBCache('main'); }
此定义的其他迭代将不起作用。
Other iterations of this definition will not work.
export const mainIndexedDBCacheFactory = function() { return new IndexedDBCache('main'); };
export let mainIndexedDBCacheFactory = function() { return new IndexedDBCache('main'); };
export let mainIndexedDBCacheFactory = () => new IndexedDBCache('main');
export
前缀是必需的,即使定义在同一文件中作为提供者
。
这篇关于创建兼容AoT的服务工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!