前些日子,工作上的需要,为了避免手工编写大量近似代码而编写了一个特定的“代码生成器”,可以将数据从 XML 配置文件中读出,然后输出合并后的代码。虽然代码内容都是直接 hard code 的,但也确实解决了不少问题,减少了相当一部分工作量。
事实上,很多情况下,我们都会需要这种“代码生成器”,就像 Word 中的邮件合并功能一样。只不过,这种生成器应当是为编程语言优化的——它应当有内置的大小写模式转换,应当有层次嵌套/循环的能力等等。基于这样的需求,我写了一个简单的但也足以应付绝大多数情况的代码生成器。
具体的不说,就看看它的输入输出好了。假设我们需要这样的代码:
namespace autoCode
{
public class RectangleShape : Shape
{
public RectangleShape(int x, int y, int width, int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
private int x = 0;
public int x
{
get { return this.x; }
set { this.x = value; }
}
private int y = 0;
public int y
{
get { return this.y; }
set { this.y = value; }
}
private int width = 100;
public int width
{
get { return this.width; }
set { this.width = value; }
}
private int height = 50;
public int height
{
get { return this.height; }
set { this.height = value; }
}
}
}
以及,
namespace autoCode
{
public class CircleShape : Shape
{
public CircleShape(int centerX, int centerY, int radius)
{
this.centerX = centerX;
this.centerY = centerY;
this.radius = radius;
}
private int centerX = 0;
public int centerX
{
get { return this.centerX; }
set { this.centerX = value; }
}
private int centerY = 0;
public int centerY
{
get { return this.centerY; }
set { this.centerY = value; }
}
private int radius = 50;
public int radius
{
get { return this.radius; }
set { this.radius = value; }
}
}
}
可以看到,这些代码是有着高度规律的。于是,我们可以编写一个数据源 XML:
<?xml version="1.0" encoding="utf-8" ?>
<shapes>
<shape name="rectangle">
<inputs>
<input name="x" type="int" default="0" />
<input name="y" type="int" default="0" />
<input name="width" type="int" default="100" />
<input name="height" type="int" default="50" />
</inputs>
</shape>
<shape name="circle">
<inputs>
<input name="centerX" type="int" default="0" />
<input name="centerY" type="int" default="0" />
<input name="radius" type="int" default="50" />
</inputs>
</shape>
</shapes>
然后再使用一定的语法编写一个模板:
<# FILE path={//shape} filename="{@name:Pascal}Shape.cs" #>
namespace autoCode
{
public class <# ={@name:Pascal} #>Shape : Shape
{
public <# ={@name:Pascal} #>Shape(<# FOREACH path={inputs/input} separator=", " #><# ={@type} #> <# ={@name:camel} #><# END FOREACH #>)
{
<# FOREACH path={inputs/input} #>
this.<# ={@name:camel} #> = <# ={@name:camel} #>;
<# END FOREACH #>
}
<# FOREACH path={inputs/input} #>
private <# ={@type} #> <# ={@name:camel} #> = <# ={@default} #>;
public <# ={@type} #> <# ={@name:Pascal} #>
{
get { return this.<# ={@name:camel} #>; }
set { this.<# ={@name:camel} #> = value; }
}
<# END FOREACH #>
}
}
这样一来,只需要通过这个工具,给定上述数据源 XML 和模板文件,即可完成所有代码文件的自动生成。