我想在Angular中使用Interface指定DI,所以我问了ChatGPT

在Angular+SpringBoot的Web应用程序中,经常会使用到DI容器。但是实际上,两者都有不同的DI方式:
– Angular -> 指定实际类进行DI
– SpringBoot -> 指定接口进行DI

在常规实现中,依赖注入(DI)意味着使用方只需关注接口,而将实现类的解决交给DI容器。因此,我曾经认为在Angular中是否也可以指定接口进行DI。

或许在Angular领域这是常识,但我之前不知道,所以问了问ChatGPT。(我有点跟不上潮流…)

与ChatGPT的对话

image.png

这家伙是个天才吗!?

太厉害了吧。。。我在2、3分钟内就了解了我想知道的事情。。。
不过,由于ChatGPT有可能说谎,我会亲自试一试。

执行

界面

export interface ServiceInterface {
  show: () => void;
}

实现类(prod)

import { Injectable } from '@angular/core';
import { ServiceInterface } from './service.interface';

@Injectable({
  providedIn: 'root',
})
export class ProdService implements ServiceInterface {
  constructor() {}

  show() {
    console.log('This is ProdService.');
  }
}

实现类(test)

import { Injectable } from '@angular/core';
import { ServiceInterface } from './service.interface';

@Injectable({
  providedIn: 'root',
})
export class TestService implements ServiceInterface {
  constructor() {}

  show() {
    console.log('This is TestService.');
  }
}

好的,只需在app.module.ts文件的providers部分设置工厂,然后在使用类中进行依赖注入就可以了。
假设在prod环境中运行时,会注入prod.service.ts,而在其他情况下会注入test.service.ts并运行。

image.png

提供无法指定给interface呢…难道是被ChatGPT骗了吗…
根据我的调查,似乎有两种方法可行:
1. 实现继承自Interface的抽象类并将抽象类指定为provide。
2. 生成与Interface相关的InjectionToken,并将其指定为provide。

我个人的喜好是使用方法二来处理。

import { environment } from 'src/environments/environment';
import { ProdService } from './service/prod.service';
import { TestService } from './service/test.service';
import { ServiceInterface } from './service/service.interface';

// environmentでインスタンス化するクラスを変えていく
const myFactory = () => {
  return environment.production ? new ProdService() : new TestService();
};

// ServiceInterfaceに紐づくInjectionTokenを生成する
export const SERVICE_TOKEN = new InjectionToken<ServiceInterface>(
  'service.interface'
);

@NgModule({
  declarations: [AppComponent, CustomTooltipComponent, CustomTooltipDirective],
  imports: [BrowserModule, AppRoutingModule, OverlayModule],
  providers: [
    {
      // 生成したInjectionTokenをprovideに指定する
      provide: SERVICE_TOKEN,
      useFactory: myFactory,
    },
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

只需编写使用类即可。

import { Component, Inject } from '@angular/core';
import { SERVICE_TOKEN } from './app.module';
import { ServiceInterface } from './service/service.interface';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  title = 'angular-sample';
  // DIする際に@InjectでInjectionTokenを指定する
  constructor(@Inject(SERVICE_TOKEN) sv: ServiceInterface) {
    sv.show();
  }
}

个人觉得用@Inject来指定InjectionToken有点微妙…
能否有其他办法呢?如果是的话,用抽象类方式来实现可能是更好的选择。

现在,确认启动

ng serve --configutaion production
image.png
ng serve
image.png

哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇哇,太厉害了!!经历了一番波折,但最终实现了我想做的事情。ChatGPT太棒了!!!

我试用过后,不是像被AI夺走工作或者自认毫无价值那样消极的感觉,而是开始对使用ChatGPT不断提升自己感到兴奋。
总之,它的信息收集效率真是非常高,甚至可以用来征求案例A和案例B哪个更好的建议。在ChatGPT的回答中,我学到了很多有益的东西。

只是,像这次一样存在着虚假信息,所以更需要深入思考,通过搜索来获取证实才是重要的。另外,由于咨询类问题也可以进行引导性讯问,ChatGPT有时会提供顾虑的答案,所以询问A和B方案的优缺点,或者提出关注公平性的问题会更好吧。

这就是上面的内容。

bannerAds