代码生成工具WuffProjects.CodeGeneration使用指南

在软件开发过程中,开发者经常需要处理大量相似的数据模型类。为了解决这一问题,T4模板被广泛用于从EntityFramework模型生成类。然而,T4模板的支持并不理想,且在Visual Studio中经常显得混乱。为了解决这一问题,WuffProjects.CodeGeneration应运而生,旨在使代码生成过程更加清晰、易读,并生成美观的代码。

随着数据模型的复杂性增加,开发者面临着需要生成大量相似模型类的挑战。T4模板虽然是一种解决方案,但其支持度不高,且在多次迭代后代码结构容易混乱。WuffProjects.CodeGeneration正是为了解决这一问题而开发的。

WuffProjects.CodeGeneration目前处于测试阶段,可以通过以下命令从NuGet下载:

PM> Install-Package WuffProjects.CodeGeneration

下载的包中包含了一些示例,展示了如何使用该工具。本文将进一步提供一些示例,帮助读者理解其用法,并判断它是否适合软件项目。

基本用法

WuffProjects.CodeGeneration完全依赖于lambda表达式,生成的代码看起来像一个庞大的代码生成树。首先,需要实例化一个CodeFile对象:

var codeFile = new CodeFile();

CodeFile的构造函数接受一个params Func<CodeFile, ICodeElement>[]参数,名为"content",基本上可以将任何想要生成的内容放入其中。

创建文件

下面是一个创建包含using、namespace和TestClass的文件的示例:

var codeFile = new CodeFile( file => file.Using("System"), file => file.Using("System.Collections.Generic"), file => file.EmptyLine(), file => file.Namespace("WuffProjects.TestCode", namespaceNode => namespaceNode.Public().Static().Class("TestClass")) );

调用codeFile.Render()方法将生成以下代码:

using System; using System.Collections.Generic; namespace WuffProjects.TestCode { public static class TestClass { } }

添加更多特性

现在让添加一个简单的Add函数:

var codeFile = new CodeFile( file => file.Using("System"), file => file.Using("System.Collections.Generic"), file => file.EmptyLine(), file => file.Namespace("WuffProjects.TestCode", namespaceNode => namespaceNode.Public().Static().Class("TestClass", classNode => classNode.Function<int>("Add", functionNode => functionNode.Parameter<int>("a"), functionNode => functionNode.Parameter<int>("b"), functionNode => functionNode.Free("return a + b;") ) ) ) );

生成的代码如下:

using System; using System.Collections.Generic; namespace WuffProjects.TestCode { public static class TestClass { Int32 Add(Int32 a, Int32 b) { return a + b; } } }

重复生成代码行

通常,希望重复代码的部分。这可以通过Repeat扩展实现。让从List<string>创建一些类:

var classNames = new List<string> { "ClassA", "ClassB", "ClassC" }; var codeFile = new CodeFile( file => file.Using("System"), file => file.Using("System.Collections.Generic"), file => file.EmptyLine(), file => file.Namespace("WuffProjects.TestCode", namespaceNode => namespaceNode.Repeat(classNames, (repeatNode, className) => repeatNode.Public().Class(className, classNode => classNode.Comment("Hello I am " + className) ) ) ) );

可以看到,参数className可以在Repeat()扩展调用下的任何深度使用。

生成更复杂的代码

现在让为测试类添加一些函数:

var functions = new[] { new { Name = "SetA", ParameterName = "aInput", Comments = new List<string> { "a", "b", "c" } }, new { Name = "SetB", ParameterName = "bInput", Comments = new List<string> { "d", "e", "f" } }, new { Name = "SetC", ParameterName = "cInput", Comments = new List<string> { "g", "h", "i" } } }; var codeFile = new CodeFile( file => file.Using("System"), file => file.EmptyLine(), file => file.Namespace("WuffProjects.TestCode", namespaceNode => namespaceNode.Public().Class("MyClass", classNode => classNode.Repeat(functions, (repeatFunctionsNode, function) => repeatFunctionsNode.Public().Function( "void", function.Name, functionNode => functionNode.Parameter<int>(function.ParameterName), functionNode => functionNode.Repeat(function.Comments, (repeatComments, comment) => repeatComments.Comment(comment) ) ) ) ) ) );

生成的代码如下:

using System; namespace WuffProjects.TestCode { public class MyClass { public void SetA(Int32 aInput) { // a // b // c } public void SetB(Int32 bInput) { // d // e // f } public void SetC(Int32 cInput) { // g // h // i } } }

代码结构优化

为了使代码结构更加清晰,避免生成一个无法维护的庞大代码树,可以将代码的某些部分分离到其他函数中。下面是一个示例:

List<string> memberNames = new List<string> { "FirstName", "LastName", "City", "Phone" }; var codeFile = new CodeFile( file => file.Using("System"), file => file.EmptyLine(), file => file.Namespace("WuffProjects.TestCode", namespaceNode => namespaceNode.Public().Static().Class("TestClass", GetFunctions(memberNames).ToArray() ) ) ); private static IEnumerable<Func<Class, ICodeElement>> GetFunctions(List<string> memberNames) { foreach (var memberName in memberNames) yield return parent => parent.Private().Static().Function<string>( "Get" + memberName, functionNode => functionNode.Comment("Returns the value of the member m_" + memberName), functionNode => functionNode.Free("return m_" + memberName + ";") ); }

生成的代码如下:

using System; namespace WuffProjects.TestCode { public static class TestClass { private static String GetFirstName() { // Returns the value of the member m_FirstName return m_FirstName; } private static String GetLastName() { // Returns the value of the member m_LastName return m_LastName; } private static String GetCity() { // Returns the value of the member m_City return m_City; } private static String GetPhone() { // Returns the value of the member m_Phone return m_Phone; } } }

WuffProjects.CodeGeneration的优势

该框架为几乎所有可能想要生成的代码结构提供了模板。不需要关心缩进,结果总是格式良好的。不需要关心任何字符串操作,它都为完成了。类型可以作为类型参数传递,所以不需要将它们写成字符串。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485