TypeScript-将类作为参数和反射进行传递



我正在编写一个通用的解组器。它将图形DB数据转换为生成的TypeScript(1.8.7)模型类。输入是JSON。输出应该是一个模型类的实例
我的最终目标是创建类似Hibernate OGM的东西,只用于Tinkerpop Frames和TypeScript,REST端点在中间

将类作为参数传递并到达其静态成员的正确方法是什么我想要这样的东西:

SomeModel some = <SomeModel> unmarshaller.fromJSON({/*Object from JSON*/}, SomeModel);

我试着写一个方法。不确定我是否正朝着正确的方向前进,请随意提出不同的方法。

public fromJSON(input: Object, clazz: typeof FrameModel): FrameModel
{
    // This only demonstrates access to Framemodel's metadata 
    // about original Java model classes.
    clazz.graphPropertyMapping;
    clazz.graphRelationMapping;
    let result = {};
    ...
    return result;
}
...

但当我试图在Plunker上执行此操作时,我遇到了不有用的stacktrace执行错误。

模型超类如下所示:

/**
 * Things common to all Frames models on the Typescript side.
 */
export class FrameModel
{
    // Model metadata
    static discriminator: string;
    static graphPropertyMapping: { [key:string]:string; };
    static graphRelationMapping: { [key:string]:string; };
    // Each instance needs a vertex ID
    private vertexId: number;
    public getVertexId(): number {
        return this.vertexId;
    }
}

样品型号类别:

import {TestPlanetModel} from './TestPlanetModel';
import {TestShipModel} from './TestShipModel';
export class TestGeneratorModel extends FrameModel
{
    static discriminator: string = 'TestGenerator';
    static graphPropertyMapping: { [key:string]:string; } = {
        bar: 'boo',
        name: 'name',
        rank: 'rank',
    };
    static graphRelationMapping: { [key:string]:string; } = {
        colonizes: 'colonizedPlanet',
        commands: 'ship',
    };
    boo: string;
    name: string;
    rank: string;
    public colonizedPlanet: TestPlanetModel[]; // edge label 'colonizedPlanet'
    public ship: TestShipModel; // edge label 'ship'
}

我在TypeScript中没有找到太多关于反射和类处理的材料
我知道用Java该怎么做
我知道用JavaScript该怎么做
我知道使用decorator可能会获得类似的结果,但对于生成的模型来说,拥有字段或静态字段似乎更简单一些。

您可能已经注意到类成员不能有const关键字。但是你可以选择static。此外,若你们想从外部世界访问,成员应该是公开的。

public static graphPropertyMapping: { [key:string]:string; } = {
    bar: 'boo',
    name: 'name',
    rank: 'rank',
};

至于创建结果实例:

let result = new clazz();
//copy properties
return result;

如果我正确理解你,那么这里有一些东西可以帮助你开始:

interface Model {}
interface ModelData {}
interface MyModelConstructor<M extends Model, D extends ModelData> {
    new(data: D): M;
    // static members
    graphPropertyMapping: any;
    graphRelationMapping: any;
}
class Unmarshaller {
    public fromJSON<T>(input: string | ModelData, ctor: MyModelConstructor<T, ModelData>): T {
        let data: ModelData = (typeof input === "string") ? JSON.parse(input) : input;
        let propertyMapping = ctor.graphPropertyMapping;
        let relationMapping = ctor.graphRelationMapping;
        // do whatever with the mappings
        return new ctor(input);
    }
}

(操场代码)

我不知道你们的模特长得怎么样,所以我希望这个足够近。

我最近发布了一个TypeScript编译器的增强版,它可以实现您所期望的功能:从类中读取所有(静态或非静态)字段元数据。例如,你可以写:

interface MyInterface {
    active:boolean;
    description: string;
}
class MyClass {
    id: number;
    name: string;
    myComplexField: MyInterface;
}
function printMembers(clazz: Class) {
    let fields = clazz.members.filter(m => m.type.kind !== 'function'); //exclude methods.
    for(let field of fields) {
        let typeName = field.type.kind;
        if(typeName === 'class' || typeName === 'interface') {
            typeName = (<Class | Interface>field.type).name;
        }
        console.log(`Field ${field.name} of ${clazz.name} has type: ${typeName}`);
    }
}
printMembers(MyClass.getClass());

这是输出:

$ node main.js
Field id of MyClass has type: number
Field name of MyClass has type: string
Field myComplexField of MyClass has type: MyInterface

当然,如果将clazz的members属性访问权限更改为statics,则将检索所有静态成员。这些信息也可以在编码时访问,因此您可以使用自动补全。您可以对接口元数据执行同样的操作。例如,只需编写MyInterface并访问其成员即可。你可以在这里找到这个项目。

相关内容

  • 没有找到相关文章

最新更新