我有一个独特的情况,我发现自己很困惑。我有一个标准的typescript类(.ts
)扩展,需要使用angular2服务中的方法。到目前为止,我无法找到实现这一目标的方法。
我会尽可能简单地尝试解释一下,因为我的代码库目前非常复杂。
有问题的服务是operation.service.ts
:
import { Injectable } from '@angular/core';
import { Http, Response, Headers } from '@angular/http';
import { Operation } from './operation';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
@Injectable()
export class OperationService {
private operationCatalogue: Operation[] = [];
private url = './src/app/operation-catalogue/operations.json';
constructor(private http:Http) {
this.init();
}
init(){
this.fetchOperations().subscribe(res => {
var i;
for(i in res["operations"]){
this.operationCatalogue[i] = new Operation(res["operations"][i]["name"],
res["operations"][i]["description"],
res["operations"][i]["iconName"],
res["operations"][i]["inputs"],
res["operations"][i]["outputs"]
);
}
});
}
getOperations(){
return this.operationCatalogue;
}
fetchOperations(): Observable<Operation[]>{
return this.http.get(this.url).map(res => res.json());
}
/*
Get a single operation from the operation catalogue.
*/
getOperation(name: String): Operation {
var theOne;
for (var i = 0; i < this.operationCatalogue.length; i++){
if (this.operationCatalogue[i].name === name){
theOne = this.operationCatalogue[i];
}
}
return theOne;
}
}
您将从此代码中看到,该服务根据本地源Operation
文件中的数据构建了这些.json
个对象。在生产中,我的应用程序将从服务器而不是本地文件中获取数据。
要注意的重要方法是getOperation()
,它接受一个字符串并从数组中返回一个Operation
对象。
此服务是我的应用程序的关键部分,用于填充另一个组件中的HTML列表。
现在,我有另一个名为WSJSerializer
的班级。简单地说,只是为了给你一些上下文,这个类接受一个JSON字符串,该字符串表示在磁盘上找到的操作对象数组,并将它们转换为Operation
个对象。 要执行此操作,WSJSerializer
需要使用getOperation()
的{{1}}方法。
OperationService
:
WSJSerializer.ts
这是我的问题的症结所在。我无法与export class WSJDeserializer {
private jsonString : string;
private parsedString : Object;
constructor(string : String){
this.jsonString = <string> string;
this.parsedString = JSON.parse(this.jsonString);
}
public deserialize() {
var rootOp = this.parsedString["operation"];
var childOps = rootOp["operations"];
var numOps = childOps.length;
for (var i = 0; i < numOps; i++){
var childOp = childOps[i]["operation"];
this.deserializeObject(childOp);
}
}
private deserializeObject(operation : Object){
//NEED TO USE THE getOperation() METHOD HERE!!!!
}
}
中的OperationService
进行交互,我猜测它是某种角度限制。我尝试WSJSerializer
import
进入OperationService
,然后调用WSJSerializer
方法,但我收到以下错误:
getOperation()
如何在WSJDeserializer.ts (25,26): Property 'getOperations' does not exist on type 'typeof OperationService'.)
内拨打getOperation()
的{{1}}方法? 如果不能直接使用,我可以吗?编写某种接口(不是OO概念接口)或辅助类来解决问题?还有其他一些解决方法吗?
其他信息:
OperationService
用于我的应用程序的根角度组件,但WSJSerializer
不是。WSJSerializer
用于根组件的子组件,根组件可通过OperationService
直接访问该组件。OperationService
不是服务,因为它需要通过调用方法直接修改其他角度组件。使用ViewChild()
的根组件:
WSJSerializer
答案 0 :(得分:2)
在当前状态WSJSerializer
必须使用DI模式(而不是Angular DI)才能获得OperationService
的实例:
export class WSJDeserializer {
...
constructor(private operationService: OperationService, string : String){
this.jsonString = <string> string;
this.parsedString = JSON.parse(this.jsonString);
}
...
private deserializeObject(operation : Object){
this.operationService.getOperation(...);
...
}
}
应该从实例化此类的注入中传递,即组件:
new WSJDeserializer(workspaceString, this.operationService)
这看起来像是一个设计问题,正确的重构解决方案可能取决于问题中没有解释的其他因素。
一种可能性是错误的东西被视为班级的实体。是否真的需要一个保持状态(parsedString
)的对象,并且能够多次反序列化它?如果没有,则序列化程序可以变为单例可注入,接受字符串作为其方法的参数:
@Injectable()
export class WSJDeserializer {
constructor(private operationService: OperationService) {}
deserialize(string : String) {
...
this.deserializeObject(string , childOp);
...
}
private deserializeObject(string : String, operation : Object){
this.operationService.getOperation(...);
...
}
}
另一种可能性是实体是正确的,但实际上需要一个保持状态的实例,因此一个类是不够的。单身注射应该以任何方式存在以获得OperationService
。所以应该有两个类而不是一个:
export class WSJDeserializable {
...
constructor(string : String){
this.jsonString = <string> string;
this.parsedString = JSON.parse(this.jsonString);
}
}
@Injectable()
export class WSJDeserializer {
constructor(private operationService: OperationService) {}
deserialize(deserializableObj: WSJDeserializable) {
...
this.deserializeObject(deserializableObj, childOp);
...
}
...
}
哪个应该从组件传递:
const deserializableObj = new WSJDeserializable(...);
deserializer.deserialize(deserializableObj);
有更多选项可以做到这一点,例如WSJDeserializer
实例可以有工厂方法创建WSJDeserializable
实例,但最后它保持单例,因为Angular服务是单例(在单个注入器中)。
答案 1 :(得分:0)
那么,您需要OperationService
内的WSJSerializer
个实例吗?只有一种方式可以做到这一点,那就是通过注入器。为了使WSJSerializer
可注射,您必须将其转换为服务。
WSJSerializer
服务,则还需要确保OperationService
也不是服务。这很容易做到。您可以使用本机库(XmlHttpRequest
或fetch
(请注意,fetch仅适用于现代浏览器),而不是使用角度Http
服务。