我的下面的解决方案是建立在以下之上的:
-
TypeScript 装饰器
- 元数据规范(早期/实验)
先决条件:
- 在 TypeScript 中启用装饰器和装饰器元数据支持
tsconfig.json
或者在命令行上:
tsconfig.json
{
"compilerOptions": {
"target": "es5", // you have to target es5+
"experimentalDecorators": true,
"emitDecoratorMetadata": true
// ....
}
// ...
}
-
Install reflect-metadata
package
npm install --save-devreflect-metadata
serializerWith
装修工(工厂)
装饰器工厂是一种接受一个或多个参数并返回 TypeScript 在生成的 JavaScript 代码中使用的装饰器函数的东西。
我选择直接将序列化函数传递到我的装饰器工厂中并使用reflect-metadata
实现元数据规范,将序列化器函数与属性关联起来。我稍后将检索它并在运行时使用它。
function serializeWith(serializer: (input: any) => string) : (target: any, propertyKey: string) => void {
return function(target: any, propertyKey: string) {
// serialization here is the metadata key (something like a category)
Reflect.defineMetadata("serialization", serializer, target, propertyKey);
}
}
Use
给定这个序列化器:
function MyDateSerializer(value : any) : string {
console.log("MyDateSerializer called");
return "dummy value";
}
然后我们可以像这样应用装饰器工厂:
import "reflect-metadata"; // has to be imported before any decorator which uses it is applied
class Greeter {
@serializeWith(MyDateSerializer)
public greeting : string;
constructor(message: string) {
this.greeting = message;
}
}
我们可以像这样获取和使用序列化器:
var greetingInstance = new Greeter("hi");
var serializerFunc : (input: any) => string = Reflect.getMetadata("serialization", greetingInstance, "greeting");
serializerFunc(greetingInstance.greeting);
Sample
main.ts
import "reflect-metadata";
function serializeWith(serializer: (input: any) => string) : (target: any, propertyKey: string) => void {
return function(target: any, propertyKey: string) {
console.log("serializeWith called: adding metadata");
Reflect.defineMetadata("serialization", serializer, target, propertyKey);
}
}
function MyDateSerializer(value : any) : string {
console.log("MyDateSerializer called");
return "bla";
}
class Greeter {
@serializeWith(MyDateSerializer)
public greeting : string;
constructor(message: string) {
console.log("Greeter constructor");
this.greeting = message;
}
}
var greetingInstance = new Greeter("hi");
var serializerFunc : (input: any) => string = Reflect.getMetadata("serialization", greetingInstance, "greeting");
var serializedValue = serializerFunc(greetingInstance.greeting);
console.log(serializedValue);
Outputs
c:\code\tmp\lll>node build\main.js
serializeWith called: adding metadata
Greeter constructor
MyDateSerializer called
bla