Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular 角度8-服务注入和工厂模式_Angular_Typescript_Dependency Injection_Factory Pattern - Fatal编程技术网

Angular 角度8-服务注入和工厂模式

Angular 角度8-服务注入和工厂模式,angular,typescript,dependency-injection,factory-pattern,Angular,Typescript,Dependency Injection,Factory Pattern,我简要地阅读了几篇文章和官方指南,但它们似乎不能帮助我解决我的任务。这就是我想要和做的 假设我有一个带有产品列表页面的Angular应用程序。此外,该应用程序将有类别列表页面和一些N个列表页面在未来。正如您所看到的,它们非常相似,在公共数据表中有一个组件 <app-data-table [type]="'product'"></app-data-table> 所以,正如您可能已经猜到的,我的意思是使这个组件服务类型不可知。这就是我创建并注入数据工厂的原因: import

我简要地阅读了几篇文章和官方指南,但它们似乎不能帮助我解决我的任务。这就是我想要和做的

假设我有一个带有产品列表页面的Angular应用程序。此外,该应用程序将有类别列表页面和一些N个列表页面在未来。正如您所看到的,它们非常相似,在公共数据表中有一个组件

<app-data-table [type]="'product'"></app-data-table>
所以,正如您可能已经猜到的,我的意思是使这个组件服务类型不可知。这就是我创建并注入数据工厂的原因:

import { Injectable } from '@angular/core';
import {ProductService} from "./product.service";
import {CategoryService} from "./category.service";
import {DataService} from "./data.service";

@Injectable({
  providedIn: 'root'
})
export class DataFactoryService {

  private serviceTokenMapping = {
    "product": ProductService,
    "category": CategoryService
  };

  constructor() { }

  public getServiceBy(token: string): DataService {
    return new this.serviceTokenMapping[token];
  }
}
最后,我们为产品和类别提供了两项服务,并提供了一些简单的基本抽象类:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export abstract class DataService {

  abstract selectAll(): any[];
}

import { Injectable } from '@angular/core';
import {DataService} from "./data.service";
import {Product} from "./product";

@Injectable({
  providedIn: 'root'
})
export class ProductService implements DataService {

  constructor() {}

  public selectAll(): Product[] {
    console.log(`ProductService...`);
    return [];
  }
}

import { Injectable } from '@angular/core';
import {DataService} from "./data.service";
import {Category} from "./category";

@Injectable({
  providedIn: 'root'
})
export class CategoryService implements DataService {

  constructor() {}

  public selectAll(): Category[] {
    console.log(`CategoryService...`);
    return [];
  }
}
有趣的是,这个实现完全按照预期工作。所以我将表的类型作为product传递给product相关页面,category类型作为category等


问题是从角度(提供者、DI等)来看,我是否做了一些不正确的事情?我们是否有任何方法来实现这样一个要求,使其更加角度化?

我认为每次触发
this.dataFactory.getServiceBy(this.type)时,您实际上都在实例化
ProductService
CategoryService
,而不是在Angular中实际使用依赖项注入

您可以使用
@NgModule
providers
属性指定每个依赖项的令牌,并使用
@Inject
injector.get获取依赖项

export interface DataService {
  selectAll(): any[];
}

@Injectable({
  providedIn: 'root'
})
export class ProductService implements DataService {
  public static TOKEN = new InjectionToken<DataService>('ProductService_TOKEN');
  constructor() {}

  public selectAll(): Product[] {
    console.log(`ProductService...`);
    return [];
  }
}

@Injectable({
  providedIn: 'root'
})
export class CategoryService implements DataService {
  public static TOKEN = new InjectionToken<DataService>('CategoryService_TOKEN');
  constructor() {}

  public selectAll(): Category[] {
    console.log(`CategoryService...`);
    return [];
  }
}

@NgModule({
    providers: [
     {
        provide: ProductService.TOKEN,
        useExisting: forwardRef(() => ProductService),
        multi: false
     },
     {
        provide: CategoryService.TOKEN,
        useExisting: forwardRef(() => CategoryService),
        multi: false
     }
   ]
})
export class YourModule {}

@Component({
  selector: 'app-data-table',
  templateUrl: './data-table.component.html',
  styleUrls: ['./data-table.component.css']
})
export class DataTableComponent implements OnInit {

  @Input() type: string;

  private data: any[];

  constructor(
     @Inject(ProductService.TOKEN) private dataService: DataService,
     private injector: Injector
   ) { }

  ngOnInit(): void {
    this.dataService.selectAll();
    this.injector.get<DataService>(CategoryService.TOKEN).selectAll();
  }

}
导出接口数据服务{
selectAll():任意[];
}
@注射的({
providedIn:'根'
})
导出类ProductService实现数据服务{
公共静态令牌=新注入令牌(“ProductService_令牌”);
构造函数(){}
public selectAll():产品[]{
log(`ProductService…`);
返回[];
}
}
@注射的({
providedIn:'根'
})
导出类CategoryService实现数据服务{
公共静态令牌=新注入令牌(“CategoryService_令牌”);
构造函数(){}
public selectAll():类别[]{
log(`CategoryService…`);
返回[];
}
}
@NGD模块({
供应商:[
{
提供:ProductService.TOKEN,
useExisting:forwardRef(()=>ProductService),
多重:假
},
{
提供:CategoryService.TOKEN,
useExisting:forwardRef(()=>CategoryService),
多重:假
}
]
})
导出类模块{}
@组成部分({
选择器:“应用程序数据表”,
templateUrl:'./data table.component.html',
样式URL:['./数据表.component.css']
})
导出类DataTableComponent实现OnInit{
@Input()类型:string;
私人数据:任何[];
建造师(
@注入(ProductService.TOKEN)私有数据服务:数据服务,
专用注射器:注射器
) { }
ngOnInit():void{
this.dataService.selectAll();
this.injector.get(CategoryService.TOKEN).selectAll();
}
}

我认为每次触发
this.dataFactory.getServiceBy(this.type)
时,您实际上都在实例化
ProductService
CategoryService
,而不是在Angular中实际使用依赖项注入

您可以使用
@NgModule
providers
属性指定每个依赖项的令牌,并使用
@Inject
injector.get获取依赖项

export interface DataService {
  selectAll(): any[];
}

@Injectable({
  providedIn: 'root'
})
export class ProductService implements DataService {
  public static TOKEN = new InjectionToken<DataService>('ProductService_TOKEN');
  constructor() {}

  public selectAll(): Product[] {
    console.log(`ProductService...`);
    return [];
  }
}

@Injectable({
  providedIn: 'root'
})
export class CategoryService implements DataService {
  public static TOKEN = new InjectionToken<DataService>('CategoryService_TOKEN');
  constructor() {}

  public selectAll(): Category[] {
    console.log(`CategoryService...`);
    return [];
  }
}

@NgModule({
    providers: [
     {
        provide: ProductService.TOKEN,
        useExisting: forwardRef(() => ProductService),
        multi: false
     },
     {
        provide: CategoryService.TOKEN,
        useExisting: forwardRef(() => CategoryService),
        multi: false
     }
   ]
})
export class YourModule {}

@Component({
  selector: 'app-data-table',
  templateUrl: './data-table.component.html',
  styleUrls: ['./data-table.component.css']
})
export class DataTableComponent implements OnInit {

  @Input() type: string;

  private data: any[];

  constructor(
     @Inject(ProductService.TOKEN) private dataService: DataService,
     private injector: Injector
   ) { }

  ngOnInit(): void {
    this.dataService.selectAll();
    this.injector.get<DataService>(CategoryService.TOKEN).selectAll();
  }

}
导出接口数据服务{
selectAll():任意[];
}
@注射的({
providedIn:'根'
})
导出类ProductService实现数据服务{
公共静态令牌=新注入令牌(“ProductService_令牌”);
构造函数(){}
public selectAll():产品[]{
log(`ProductService…`);
返回[];
}
}
@注射的({
providedIn:'根'
})
导出类CategoryService实现数据服务{
公共静态令牌=新注入令牌(“CategoryService_令牌”);
构造函数(){}
public selectAll():类别[]{
log(`CategoryService…`);
返回[];
}
}
@NGD模块({
供应商:[
{
提供:ProductService.TOKEN,
useExisting:forwardRef(()=>ProductService),
多重:假
},
{
提供:CategoryService.TOKEN,
useExisting:forwardRef(()=>CategoryService),
多重:假
}
]
})
导出类模块{}
@组成部分({
选择器:“应用程序数据表”,
templateUrl:'./data table.component.html',
样式URL:['./数据表.component.css']
})
导出类DataTableComponent实现OnInit{
@Input()类型:string;
私人数据:任何[];
建造师(
@注入(ProductService.TOKEN)私有数据服务:数据服务,
专用注射器:注射器
) { }
ngOnInit():void{
this.dataService.selectAll();
this.injector.get(CategoryService.TOKEN).selectAll();
}
}

您应该仔细检查是否可以删除DataServiceFactory类并直接注入所需的服务。您还应该扩展抽象类(
extends
而不是
implements
)@ChristophLütjen感谢您的及时回复!你能举一些你建议的例子吗?如果我正在创建组件(new DataTableComponent(new ProductService()),我可以将服务注入组件,但它是由Angular injector创建的。我们使用指令解决了相同的问题。这里有一个选择器,如
data table[products]
,您可以将数据表注入指令(并从那里设置dataTable.data)。我们这样做是为了解决“依赖于所有可用数据提供程序”的问题。您应该仔细检查是否可以删除DataServiceFactory类并直接注入所需的服务。此外,您还应该扩展抽象类(
扩展
,而不是
实现
)@ChristophLütjen感谢您的及时回复!您能给出一些您建议的示例吗?如果我正在创建组件(new DataTableComponent(new ProductService()),我可以将服务注入组件,但它是在