使用 TypeWriter 有条件地发出方法
Conditionally emitting a method with TypeWriter
我正在使用 TypeWriter 从我的 C# 模型生成 TypeScript classes。它很好用。以下是我的 existing 模板的完整内容,效果很好:
${
using Typewriter.Extensions.Types;
Template(Settings settings)
{
settings.IncludeProject("ProjectName.Api");
settings.OutputFilenameFactory = file =>
{
return file.Name.Replace("Dto.cs", ".ts");
};
}
string DtoName(Class t) { return t.Name.Replace("Dto", ""); }
string MapTypeName(Property p) { return MapTypeName(p.Type); }
string MapTypeName(Type t)
{
var typeArguments = t.TypeArguments.ToList();
if (typeArguments.Count == 1 && t.IsEnumerable)
{
return $"{MapTypeName(typeArguments[0])}[]";
}
if (typeArguments.Count == 2 && t.Name == $"KeyValuePair<{typeArguments[0]}, {typeArguments[1]}>")
{
return $"{{ key: {typeArguments[0]}; value: {typeArguments[1]}}}";
}
return t.Name.Replace("Dto", "");
}
}
module CompanyName.Models.Api {
$Classes(ProjectName.Api.Models.*Dto)[
export class $DtoName {
$Properties[
public $name: $MapTypeName = $Type[$Default];]
}]
}
我想针对特定类型有条件地向此模板添加方法。我认为这样的事情会奏效:
module CompanyName.Models.Api {
$Classes(ProjectName.Api.Models.*Dto)[
export class $DtoName {
$Properties[
public $name: $MapTypeName = $Type[$Default];]
${
if ($name == "ADto")
{
// I want to emit this code:
// public getStatistic(appType: string, status: string): number {
// const retval = _.find(this.data, { appType: appType, status: status });
// return retval ? retval.count : 0;
// }
}
}
}]
}
但它不喜欢这种语法,我收到 5 个打字机错误,包括 "unexpected token" 和 "invalid token"。我尝试了这个的变体:
module CompanyName.Models.Api {
$Classes(ProjectName.Api.Models.*Dto)[
export class $DtoName {
$Properties[
public $name: $MapTypeName = $Type[$Default];]
$if ($name == "ADto")
{
// I want to emit this code:
// public getStatistic(appType: string, status: string): number {
// const retval = _.find(this.data, { appType: appType, status: status });
// return retval ? retval.count : 0;
// }
}
}]
}
但是打字机发出整个 $if { ... }
块,这不是我想要的。
我是否必须专门为此 class 创建第二个模板,或者我可以使用条件来创建第二个模板吗?如果是,怎么做?
我想通了,基于this Github issue comment
在主体中,在模板之上,添加这个辅助函数:
bool IsStatisticsClass(Class c)
{
return c.Name == "ADto";
}
这为我们提供了某种包装器(我不确定正确的术语是什么)。我们可以使用 $IsStatisticsClass[ ... ]
来有条件地添加代码。模板本身变为:
module CompanyName.Models.Api {
$Classes(ProjectName.Api.Models.*Dto)[
export class $DtoName {
$Properties[
public $name: $MapTypeName = $Type[$Default];]
$IsStatisticsClass[
// This code is now emitted for a single class:
// public getStatistic(appType: string, status: string): number {
// const retval = _.find(this.data, { appType: appType, status: status });
// return retval ? retval.count : 0;
// }]
}]
}
为了与我的问题保持一致,我将发出的 TypeScript 代码注释掉了。
我正在使用 TypeWriter 从我的 C# 模型生成 TypeScript classes。它很好用。以下是我的 existing 模板的完整内容,效果很好:
${
using Typewriter.Extensions.Types;
Template(Settings settings)
{
settings.IncludeProject("ProjectName.Api");
settings.OutputFilenameFactory = file =>
{
return file.Name.Replace("Dto.cs", ".ts");
};
}
string DtoName(Class t) { return t.Name.Replace("Dto", ""); }
string MapTypeName(Property p) { return MapTypeName(p.Type); }
string MapTypeName(Type t)
{
var typeArguments = t.TypeArguments.ToList();
if (typeArguments.Count == 1 && t.IsEnumerable)
{
return $"{MapTypeName(typeArguments[0])}[]";
}
if (typeArguments.Count == 2 && t.Name == $"KeyValuePair<{typeArguments[0]}, {typeArguments[1]}>")
{
return $"{{ key: {typeArguments[0]}; value: {typeArguments[1]}}}";
}
return t.Name.Replace("Dto", "");
}
}
module CompanyName.Models.Api {
$Classes(ProjectName.Api.Models.*Dto)[
export class $DtoName {
$Properties[
public $name: $MapTypeName = $Type[$Default];]
}]
}
我想针对特定类型有条件地向此模板添加方法。我认为这样的事情会奏效:
module CompanyName.Models.Api {
$Classes(ProjectName.Api.Models.*Dto)[
export class $DtoName {
$Properties[
public $name: $MapTypeName = $Type[$Default];]
${
if ($name == "ADto")
{
// I want to emit this code:
// public getStatistic(appType: string, status: string): number {
// const retval = _.find(this.data, { appType: appType, status: status });
// return retval ? retval.count : 0;
// }
}
}
}]
}
但它不喜欢这种语法,我收到 5 个打字机错误,包括 "unexpected token" 和 "invalid token"。我尝试了这个的变体:
module CompanyName.Models.Api {
$Classes(ProjectName.Api.Models.*Dto)[
export class $DtoName {
$Properties[
public $name: $MapTypeName = $Type[$Default];]
$if ($name == "ADto")
{
// I want to emit this code:
// public getStatistic(appType: string, status: string): number {
// const retval = _.find(this.data, { appType: appType, status: status });
// return retval ? retval.count : 0;
// }
}
}]
}
但是打字机发出整个 $if { ... }
块,这不是我想要的。
我是否必须专门为此 class 创建第二个模板,或者我可以使用条件来创建第二个模板吗?如果是,怎么做?
我想通了,基于this Github issue comment
在主体中,在模板之上,添加这个辅助函数:
bool IsStatisticsClass(Class c)
{
return c.Name == "ADto";
}
这为我们提供了某种包装器(我不确定正确的术语是什么)。我们可以使用 $IsStatisticsClass[ ... ]
来有条件地添加代码。模板本身变为:
module CompanyName.Models.Api {
$Classes(ProjectName.Api.Models.*Dto)[
export class $DtoName {
$Properties[
public $name: $MapTypeName = $Type[$Default];]
$IsStatisticsClass[
// This code is now emitted for a single class:
// public getStatistic(appType: string, status: string): number {
// const retval = _.find(this.data, { appType: appType, status: status });
// return retval ? retval.count : 0;
// }]
}]
}
为了与我的问题保持一致,我将发出的 TypeScript 代码注释掉了。