我有一个独特的情况,我发现自己被困住了。我有一个标准的类型记录类(.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() 需要使用 OperationService**.**的getOperation()方法。
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() OperationService 的方法(不是OO概念接口)或助手类来解决问题,那么如何从 WSJSerializer**?** 中调用方法呢?还有其他解决办法吗?
其他资料:
WSJSerializer在我的应用程序的根角组件中使用,但OperationService不是。OperationService在根组件的子组件中使用,根组件可以通过ViewChild()直接访问根组件。WSJSerializer不是一个服务,因为它需要通过调用其他角度组件的方法来直接修改它们。使用WSJSerializer的根组件:
import { WSJDeserializer } from './serialization/WSJDeserializer';
//services...
import { SerializationService } from './serialization/serialization.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [SerializationService]
})
export class AppComponent implements OnInit {
@ViewChild(PixiComponent) private pixiComponent : PixiComponent;
@ViewChild(LogComponent) private logComponent : LogComponent;
@ViewChild(EditGlobalNamesDialogBoxComponent) private globalNamesEditDialog : EditGlobalNamesDialogBoxComponent;
@ViewChild(GlobalNamesComponent) private globalNamesComponent : GlobalNamesComponent;
private globalNamesController : GlobalNamesController;
ngOnInit() {
this.globalNamesController = new GlobalNamesController(this.globalNamesEditDialog, this.globalNamesComponent, this.pixiComponent);
}
public leftMousedown(){
this.pixiComponent.clickFromOutside();
}
public rightMousedown($event){
$event.preventDefault();
this.pixiComponent.clickFromOutside();
}
//TODO: Escape key functionality
notifyEscapePressed(){
}
/*------------------------------------------------------------------------*/
// Following method for log functionality
public logData($event){
this.logComponent.logText($event);
}
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
// Following methods for global names functionality
// handled by this.globalNamesController
public globalNameEditRequest(data : EditGlobalNameRequestData){
this.globalNamesController.displayEditGlobalNamesDialogBox(data);
}
public setNewGlobalName(data : EditGlobalNameRequestData) {
this.globalNamesController.setNewGlobalName(data);
}
/*------------------------------------------------------------------------*/
/*------------------------------------------------------------------------*/
// Deserialization...
public deserialize($event){
var workspaceString : String = $event;
var deserializer : WSJDeserializer = new WSJDeserializer(workspaceString)
this.pixiComponent.resetCanvas();
deserializer.deserialize();
}
/*------------------------------------------------------------------------*/
}发布于 2017-04-24 03:46:05
在当前状态下,WSJSerializer必须使用DI模式(而不是角度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实例的工厂方法,但是最终它仍然是一个单例,因为角服务是单个的(在单个注入器中)。
发布于 2017-04-24 02:54:59
那么,您需要OperationService在WSJSerializer中的一个实例吗?只有一种方法可以做到这一点,那就是通过注射器。为了使WSJSerializer可注入,必须将其转换为服务。
嗯,这是个小谎言。还有另一种方法。如果不能使WSJSerializer成为服务,那么还需要确保OperationService也不是服务。这很容易做到。您可以使用本机库而不是使用Http服务( XmlHttpRequest或fetch )(注意,只在现代浏览器上进行抓取)。
https://stackoverflow.com/questions/43578519
复制相似问题