ServiceStack - 如何添加自定义打字稿装饰器?

ServiceStack - how to add custom typescript decorators?

我正在通过 ServiceStack 下的 C# 模型生成打字稿 dto。

我希望使用 typestack/class-validator,它通过评估它提供的几个装饰器来运行。

在 ServiceStack 的打字稿生成中,是否有一种方法可以在 C# 端包含超出常规 DataAnnotations 属性的任意装饰器,或者我必须创建新的 C# 属性来反映我想在打字稿端显示的内容?

编辑:

由于 更 UX-friendly 我还决定实现此功能,您可以在其中使用 [Emit{Language}] 属性在每种类型或 属性 之前生成代码,例如:

[EmitTypeScript("@Validate()")]
public class User
{
    [EmitTypeScript("@IsNotEmpty()", "@IsEmail()")]
    public string Email { get; set; }
}

您还可以使用 [EmitCode] 发出多种语言的代码,例如这会为 Dart 和 TypeScript 添加注释。

[EmitCode(Lang.Dart | Lang.TypeScript, "@Validate()")]
public class User
{
    [EmitCode(Lang.Dart | Lang.TypeScript, new[]{ "@IsNotEmpty()", "@IsEmail()" })]
    public string Email { get; set; }
}

此外,您可以使用 PreTypeFilterInnerTypeFilterPostTypeFilter 在类型定义前后生成源代码,例如这将在非枚举类型上附加 @validate() 注释:

TypeScriptGenerator.PreTypeFilter = (sb, type) => {
    if (!type.IsEnum.GetValueOrDefault())
    {
        sb.AppendLine("@Validate()");
    }
};

InnerTypeFilter 在类型定义之后被调用,可用于为所有类型和接口生成公共成员,例如:

TypeScriptGenerator.InnerTypeFilter = (sb, type) => {
    sb.AppendLine("id:string = `${Math.random()}`.substring(2);");
};

它们以前不存在,但我也刚刚添加了 PrePropertyFilter & PostPropertyFilter 用于在属性前后生成源代码,例如:

TypeScriptGenerator.PrePropertyFilter = (sb , prop, type) => {
    if (prop.Name == "Id")
    {
        sb.AppendLine("@IsInt()");
    }
};

Pre/Post PropertyFilter 从 v5.9.3+ 开始可用,现在是 available on MyGet.

在@mythz 增强功能之上,这是我最终目标的简洁镜头...

定义 c# 属性 class 以允许使用装饰器装饰 c# 属性,并将代码生成到相应的打字稿 dtos 中:

[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
public class TypeScriptDecoratorsAttribute : Attribute
{
    public string[] Decorators { get; set; }
    public TypeScriptDecoratorsAttribute(params string[] decorators)
    {
        this.Decorators = decorators;
    }
}

然后使用新的 PrePropertyFilter 发出: (例如 Startup.cs)

TypeScriptGenerator.PrePropertyFilter = (sb, prop, type) => 
  prop.PropertyInfo.FirstAttribute<TypeScriptDecoratorsAttribute>()?.Decorators?.ForEach(d=> sb.AppendLine("// "+d));

仅供参考,Enumerable.ForEach() 来自 System.Interactive.

所以这个示例 c# dto:

public class User
{
    [TypeScriptDecorators("@IsNotEmpty()", "@IsEmail()")]
    public string Email { get; set; }
}

将产生此打字稿 dto 输出:

export class User
{
    // @IsNotEmpty()
    // @IsEmail()
    public email?: string;

    public constructor(init?: Partial<User>) { (Object as any).assign(this, init); }
}