Reflection TypeScript-将类作为参数传递,并进行反射
我正在写一个通用的解组器。它将图形数据库数据转换为生成的TypeScript(1.8.7)模型类。输入是JSON。输出应该是模型类的实例。Reflection TypeScript-将类作为参数传递,并进行反射,reflection,typescript,marshalling,unmarshalling,Reflection,Typescript,Marshalling,Unmarshalling,我正在写一个通用的解组器。它将图形数据库数据转换为生成的TypeScript(1.8.7)模型类。输入是JSON。输出应该是模型类的实例。 我的最终目标是创建像Hibernate OGM这样的东西,只适用于TIKEPOP框架和TypeScript,中间有REST端点。 将类作为参数传递并到达其静态成员的正确方法是什么?我希望有如下内容: SomeModel some = <SomeModel> unmarshaller.fromJSON({/*Object from JSON*/},
我的最终目标是创建像Hibernate OGM这样的东西,只适用于TIKEPOP框架和TypeScript,中间有REST端点。 将类作为参数传递并到达其静态成员的正确方法是什么?我希望有如下内容:
SomeModel some = <SomeModel> unmarshaller.fromJSON({/*Object from JSON*/}, SomeModel);
/**
* 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;
}
}
但当我试图在Plunker上执行此操作时,我得到了执行错误和无用的stacktrace
模型超类如下所示:
SomeModel some = <SomeModel> unmarshaller.fromJSON({/*Object from JSON*/}, SomeModel);
/**
* 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实现这一点。
我知道我可能会使用装饰器获得类似的结果,但对于生成的模型,使用字段或静态字段似乎更简单。您可能已经注意到类成员不能使用
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);
}
}
接口模型{}
接口模型数据{}
接口MyModelConstructor{
新(数据:D):M;
//静态成员
graphPropertyMapping:任意;
graphRelationMapping:任何;
}
类解组器{
public-fromJSON(输入:string | ModelData,ctor:MyModelConstructor):T{
let data:ModelData=(typeof input==“string”)?JSON.parse(input):input;
设propertyMapping=ctor.graphPropertyMapping;
让relationMapping=ctor.graphRelationMapping;
//对映射执行任何操作
返回新的ctor(输入);
}
}
()
我不知道您的模型是什么样子,所以我希望这已经足够接近了。我最近发布了一个增强版的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());
当然,如果您将clazz的成员
属性访问更改为静态
,您将检索所有静态成员。这些信息也可以在编码时访问,所以您可以使用自动补全。
您可以对接口元数据执行相同的操作。例如,只需编写MyInterface
,并访问其成员。
你可以找到这个项目。调用
类是很传统的做法。
klass:)对,上面的例子是手工编写的,所以包含了这些错误。我真的很想知道TypeScript是如何实现和限制“静态”的——因为在JavaScript中,没有什么是真正静态的,它是绑定到函数的。从技术上讲,如果你从一个函数继承,我猜类继承是如何在TS中完成的,你也继承了静态字段吗?因此,MyClass.staticField
在技术上也可以作为MySubclass.staticField
访问?除非TS坚持Java的static
…是MyClass.staticField
也可以作为MySubclass.staticField
访问。您是对的,它绑定到函数(类定义),这看起来很合理。能否请您添加一些链接,说明接口需求背后的基本原理?我的意思是,在Java中,不需要接口来检查类元数据和注释。这是一种“官方”方式还是利用某些副作用?谢谢你的打字脚本,你不必使用它们,但它是有意义的。在我的示例中,我没有使用元数据或注释,这里唯一的东西是表示对类的引用(而不是对实例的引用)的接口:MyModelConstructor
。如果你能更具体地说明你想知道什么,我会修改我的答案以适应这个问题。我对你的例子理解得更多一些。看起来您建议每个模型都有一个构造函数类。即,每个模型都有各自的构造函数类。因为我生成了模型,所以我更希望只有一个服务类能够利用模型类中的JSON数据和元数据构建模型。我想我会改进我的问题代码。你不需要有不同的ctor类,你只需要一个,这取决于你。另外,你不需要我包含的泛型部分,在我看来这更容易,并且不需要在以后进行强制转换。但是,由于您没有包括如何创建这些模型的实例,我很难给您一个更具体的答案。我还没有创建实例。这是我还没有弄清楚的事情之一。我最初的想法是创建一个具有特定模型所需的相应属性的对象
,然后对其进行强制转换。