务实的程序员代码生成练习

时间:2010-08-10 12:30:40

标签: c# code-generation t4

我正在阅读The Pragmatic程序员并在.net世界中进行以下练习(第3章 - 代码生成器)

练习

“编写一个代码生成器,它接受清单1中的输入,并以您选择的两种语言生成输出。尝试使添加新语言变得容易。”

清单1  #添加产品
 #到'按顺序'列表
 M AddProduct
 F id int
 F name char [30]
 F order_code int
 E

你如何在T4或.net世界中的任何其他东西(CodeDOM太复杂)中实现解决方案,以便我们可以用c#和另一种.net语言(visual basic或IronRuby等)生成代码。 p>

3 个答案:

答案 0 :(得分:1)

我知道你说CodeDOM过于复杂,但我建议使用CodeDOM =)。以下是一个简短的示例:http://asp.dotnetheaven.com/howto/doc/listbuilder.aspx。对于您的示例,您可能希望将CodeMemberMethod添加到CodeTypeDeclaration的成员 - MSDN有一些示例。

T4可行,但我认为这种情况并不理想。

答案 1 :(得分:1)

我认为这不是一个使用现有代码生成器的练习。实际上还有很多东西。我相信,目标是构建自己的代码生成器,特定于域的语言,并处理解析和可扩展性/可插拔性等概念。也许我正在阅读太多的练习,但也许更多的是开发核心开发人员的技能/知识,而不是教育现有的工具。

答案 2 :(得分:1)

考虑到Ben Griswold的建议,我认为自己实施它是个好主意。虽然只是在C#中实现代码生成器,但我意识到了一些事情 -
1.需要像Python等文本操作语言 2.需要学习正则表达式

我打算在Ruby中实现它,但是现在,我用C#实现了它 -

static void Main(string[] args)
{
    CodeGenerator gen = new CodeGenerator();
    gen.ReadFile("Input.txt");
}
public class CodeGenerator
{
    public void ReadFile(string filename)
    {
        StreamReader fs = new StreamReader(filename);
        string line;
        CSharpCode CG = new CSharpCode();

        while ((line = fs.ReadLine()) != null)
        {
            line = line.TrimEnd('\n');

            if (Regex.IsMatch(line, @"^\s*S"))
                CG.BlankLine();
            else if (Regex.IsMatch(line, @"^\#(.*)")) // match comments
                CG.Comment(line.TrimStart('#'));
            else if (Regex.IsMatch(line, @"^M\s*(.+)")) // start msg
                CG.StartMsg(line.Split(' ')[1]);
            else if (Regex.IsMatch(line, @"^E")) // end msg
                CG.EndMsg();
            else if (Regex.IsMatch(line, @"^F\s*(\w+)")) // simple type
                CG.SimpleType(Regex.Split(line, @"^F\s*(\w+)")[1], Regex.Split(line, @"^F\s*(\w+)")[2]);
            else
                Console.WriteLine("Invalid line " + line);
        }
    }
}

// Code Generator for C#
public class CSharpCode
{
    public void BlankLine() { Console.WriteLine(); }
    public void Comment(string comment) { Console.WriteLine("//" + comment); }
    public void StartMsg(string name) { Console.WriteLine("public struct " + name + "{"); }
    public void EndMsg() { Console.WriteLine("}"); }
    public void SimpleType(string name, string type)
    {
        if(type.Contains("char["))
            type = "string";

        Console.WriteLine(string.Format("\t{0} {1};", type.Trim(), name));
    }
}