我尝试通过给定的字符串创建/投射对象。
我已经可以通过给定的原型来投射对象。但是我需要将内部对象强制转换为它们的类,以使用特定的属性。
我的第一种方法是使用接口并使用它扩展/继承我的模型。当我执行“静态转换方法”时,当前的原型未定义。
//IBaseModel.ts
class IBaseModel {
constructorClass: string;
constructor() {
this.constructorClass = this.constructor.name;
}
static fromJSON(json: any){
if(typeof json === 'string') {
//use second parameter "reviver" for JSON.parse, definition see below.
return JSON.parse(json, InterfaceBaseModel.reviver)
} else {
let obj = eval(`new ${json.constructorClass}()`), //eval "new Test()"
retval = Object.assign(obj, json); //assign each property
for(let prop in retval) {
//every property that contains the property constructorClass should be casted as well.
if(retval[prop].constructorClass)
retval[prop] = InterfaceBaseModel.fromJSON(retval[prop]);
}
return retval;
}
}
static reviver(key: string, value: any): any {
//every property that contains the property constructorClass should be casted as well.
return value.constructorClass ? InterfaceBaseModel.fromJSON(value) : value;
}
}
//Test.ts
import IBaseModel from 'path';
import SubTest from 'path';
class Test extends IBaseModel {
text: string;
subTest: SubTest;
constructor(text: string, subTest: SubTest) {
super();
this.text = text;
this.subTest = subTest;
}
}
//SubTest.ts
import IBaseModel from 'path';
class SubTest extends IBaseModel {
value: number;
constructor(value: number) {
super();
this.value = value;
}
}
//test.service.ts
import Test from 'path';
export class TestService {
constructor() { }
setLocalData(key: string, value: any) {
localStorage.setItem(key, value);
}
getLocalData(key: string){
let localData = localStorage.getItem(key),
retval;
if(localData)
retval = Test.fromJSON(localData);
//ERROR in "IBaseModel.ts": Test is not defined.
//Importing the class is NO option!
//As we want to use it for many classes!
return retval;
}
}
如上所述,由于未定义当前类和子类,因此我在BaseModel内部遇到错误。
我的下一个方法是为给定的“类类型”编写一个转换函数。
//castObject.ts
export function castObject<T>(json: any, type: IConstructor<T>){
if(typeof json === 'string')
return JSON.parse(json, reviver)
else {
let obj = this.activator(type),
retval = Object.assign(obj, json);
//until here it works like a charm!
for(let prop in retval) {
if(retval[prop].constructorClass)
retval[prop] = castObject<T>(retval[prop], type);
//the type for sub-classes is not given...
//SubTest is casted to Test
}
return retval;
}
}
function reviver(key: string, value: any): any {
return value.constructorClass ? castObject(value) : value;
}
function activator<T>(type: IConstructor<T>): T {
//create a new instance of the given type.
return new type();
}
interface IConstructor<T> {
//a typeless constructor, to surpass every class-type
new (...args: any[]): T;
}
//test.service.ts
import { castObject } from 'path'
...
getLocalData(key: string){
...
retval = castObject<Test>(localData, Test);
//sub-classes are getting the wrong type.
}
我的最后一种方法是使用字符串强制转换对象。像这样:
for(let prop in retval) {
if(retval[prop].constructorClass)
retval[prop] = retval[prop] as retval[prop].constructorClass;
}
我没有发现任何有关基于字符串(构造函数名称)强制转换对象的信息。
也许您可以帮助我或引导我解决正确的问题。