Angular DI 使用模型注入令牌 class
Angular DI using injection token for model class
我想在这里做点什么,但不确定是否可以完成。
我想创建一个这样的模型 class:
import { Inject } from '@angular/core';
import {
Element,
Image,
} from '@situlive/situ-angular-components/contentful';
export class ImageColumn {
title: string;
backgroundImage: Image;
backgroundImageAlignment: string;
constructor(
element: Element
) {
this.title = element.fields.title;
this.backgroundImageAlignment = element.fields.backgroundImageAlignment;
}
}
这样我就可以在组件或服务中执行 new ImageColumn(element)
,它会为我绑定属性。
到目前为止很简单。
现在我遇到了麻烦 :) 我需要绑定 backgroundImage,这是通过服务完成的。我将构造函数更新为:
import { Inject } from '@angular/core';
import {
ContentfulService,
Element,
Image,
} from '@situlive/situ-angular-components/contentful';
export class ImageColumn {
title: string;
backgroundImage: Image;
backgroundImageAlignment: string;
constructor(
contentfulService: ContentfulService,
element: Element
) {
this.title = element.fields.title;
this.backgroundImageAlignment = element.fields.backgroundImageAlignment;
this.backgroundImage = this.contentfulService.createImage(
element.fields.backgroundImage[0]
);
}
}
这很好,但会导致问题,因为现在我在任何使用 ImageColumn 的地方都必须传入 contentfulService.我真的很想能够传递服务而无需在构造函数中提供它。
我之前在使用 注入令牌 的服务中做过这件事,所以我想我可以在这里做。
我创建了一个这样的注入令牌:
import { InjectionToken } from '@angular/core';
import { ContentfulService } from '@situlive/situ-angular-components/contentful';
export const CONTENTFUL_SERVICE = new InjectionToken<ContentfulService>(
'CONTENTFUL_SERVICE'
);
我在我的模块中提供的是这样的:
@NgModule({
imports: [
CommonModule,
HttpClientModule,
RouterModule,
AuthModule.forRoot(environment.auth0),
ContentfulModule.forRoot(environment.contentful),
],
declarations: [FooterComponent, HeaderComponent],
exports: [FooterComponent, HeaderComponent],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: BearerInterceptor,
multi: true,
},
{
provide: CONTENTFUL_SERVICE,
useClass: ContentfulService,
multi: true,
},
],
})
export class CoreModule {}
所以我想我可以对我的模型这样做:
import { Inject } from '@angular/core';
import {
ContentfulService,
Element,
Image,
} from '@situlive/situ-angular-components/contentful';
import { CONTENTFUL_SERVICE } from '../contentful-service.token';
export class ImageColumn {
title: string;
backgroundImage: Image;
backgroundImageAlignment: string;
constructor(
@Inject(CONTENTFUL_SERVICE) private contentfulService: ContentfulService,
element: Element
) {
this.title = element.fields.title;
this.backgroundImageAlignment = element.fields.backgroundImageAlignment;
this.backgroundImage = this.contentfulService.createImage(
element.fields.backgroundImage[0]
);
}
}
问题是,现在当我执行 new ImageColumn(element)
时,它会抱怨我需要 2 个参数,但只得到 1 个。
有谁知道我该如何解决这个问题?
我认为这样不行,因为您没有为 ImageColumn
声明任何 提供者。声明提供者将使 注入器 知道如何在注入 ImageColumn
时获取依赖项,如下所示:
constructor (imageColumn: ImageColumn) { }
但由于您想手动实例化它,我不确定您能否让Angular知道如何自动解析注入令牌。
我认为您可以做的是在实例化 ImageColumn
时提供 Injector
。
foo.component.ts
export class FooComponent {
constructor (private injector: Injector) { }
ngOnInit () {
const imgColumn = new ImageColumn(element, this.injector)
}
}
然后在您的 ImageColumn
的构造函数中,您可以注入任何已声明提供者的内容,包括该服务:
class ImageColumn {
constructor (private element: any, private injector: Injector) {
this.contentfulService = this.injector.get(ContentfulService);
/* ... */
this.backgroundImage = this.contentfulService.createImage(
element.fields.backgroundImage[0]
);
}
}
我想在这里做点什么,但不确定是否可以完成。 我想创建一个这样的模型 class:
import { Inject } from '@angular/core';
import {
Element,
Image,
} from '@situlive/situ-angular-components/contentful';
export class ImageColumn {
title: string;
backgroundImage: Image;
backgroundImageAlignment: string;
constructor(
element: Element
) {
this.title = element.fields.title;
this.backgroundImageAlignment = element.fields.backgroundImageAlignment;
}
}
这样我就可以在组件或服务中执行 new ImageColumn(element)
,它会为我绑定属性。
到目前为止很简单。
现在我遇到了麻烦 :) 我需要绑定 backgroundImage,这是通过服务完成的。我将构造函数更新为:
import { Inject } from '@angular/core';
import {
ContentfulService,
Element,
Image,
} from '@situlive/situ-angular-components/contentful';
export class ImageColumn {
title: string;
backgroundImage: Image;
backgroundImageAlignment: string;
constructor(
contentfulService: ContentfulService,
element: Element
) {
this.title = element.fields.title;
this.backgroundImageAlignment = element.fields.backgroundImageAlignment;
this.backgroundImage = this.contentfulService.createImage(
element.fields.backgroundImage[0]
);
}
}
这很好,但会导致问题,因为现在我在任何使用 ImageColumn 的地方都必须传入 contentfulService.我真的很想能够传递服务而无需在构造函数中提供它。
我之前在使用 注入令牌 的服务中做过这件事,所以我想我可以在这里做。 我创建了一个这样的注入令牌:
import { InjectionToken } from '@angular/core';
import { ContentfulService } from '@situlive/situ-angular-components/contentful';
export const CONTENTFUL_SERVICE = new InjectionToken<ContentfulService>(
'CONTENTFUL_SERVICE'
);
我在我的模块中提供的是这样的:
@NgModule({
imports: [
CommonModule,
HttpClientModule,
RouterModule,
AuthModule.forRoot(environment.auth0),
ContentfulModule.forRoot(environment.contentful),
],
declarations: [FooterComponent, HeaderComponent],
exports: [FooterComponent, HeaderComponent],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: BearerInterceptor,
multi: true,
},
{
provide: CONTENTFUL_SERVICE,
useClass: ContentfulService,
multi: true,
},
],
})
export class CoreModule {}
所以我想我可以对我的模型这样做:
import { Inject } from '@angular/core';
import {
ContentfulService,
Element,
Image,
} from '@situlive/situ-angular-components/contentful';
import { CONTENTFUL_SERVICE } from '../contentful-service.token';
export class ImageColumn {
title: string;
backgroundImage: Image;
backgroundImageAlignment: string;
constructor(
@Inject(CONTENTFUL_SERVICE) private contentfulService: ContentfulService,
element: Element
) {
this.title = element.fields.title;
this.backgroundImageAlignment = element.fields.backgroundImageAlignment;
this.backgroundImage = this.contentfulService.createImage(
element.fields.backgroundImage[0]
);
}
}
问题是,现在当我执行 new ImageColumn(element)
时,它会抱怨我需要 2 个参数,但只得到 1 个。
有谁知道我该如何解决这个问题?
我认为这样不行,因为您没有为 ImageColumn
声明任何 提供者。声明提供者将使 注入器 知道如何在注入 ImageColumn
时获取依赖项,如下所示:
constructor (imageColumn: ImageColumn) { }
但由于您想手动实例化它,我不确定您能否让Angular知道如何自动解析注入令牌。
我认为您可以做的是在实例化 ImageColumn
时提供 Injector
。
foo.component.ts
export class FooComponent {
constructor (private injector: Injector) { }
ngOnInit () {
const imgColumn = new ImageColumn(element, this.injector)
}
}
然后在您的 ImageColumn
的构造函数中,您可以注入任何已声明提供者的内容,包括该服务:
class ImageColumn {
constructor (private element: any, private injector: Injector) {
this.contentfulService = this.injector.get(ContentfulService);
/* ... */
this.backgroundImage = this.contentfulService.createImage(
element.fields.backgroundImage[0]
);
}
}