如何根据另一个类生成代码?
为了创建测试数据,我们使用构建器模式的以下变体(简化示例!):
示例类:
public class Person
{
public string Name { get; set; }
public string Country { get; set; }
}
构建器:
public class PersonBuilder
{
private string name;
private string country;
public PersonBuilder()
{
SetDefaultValues();
}
private void SetDefaultValues()
{
name = "TODO";
country = "TODO";
}
public Person Build()
{
return new Person
{
Name = name,
Country = country
};
}
public PersonBuilder WithName(string name)
{
this.name = name;
return this;
}
public PersonBuilder WithCountry(string country)
{
this.country = country;
return this;
}
}
注意:示例本身的上下文不相关。这里重要的是,在示例中,如何通过查看实体类(Person)并应用相同的模式来完全生成像 PersonBuilder 这样的构建器类 - 见下文。
现在想象一下,Person 类有 15 个属性,而不是 2 个。实现构建器类需要一些功夫,而理论上,它可以从 Person 类自动生成。我们可以使用代码生成来快速设置构建器类,并在需要时添加自定义代码。
代码生成过程必须了解上下文(person 类的名称和属性),因此简单的基于文本的代码生成或正则表达式魔法在这里感觉不正确。首选动态的、非基于文本的、并且可以从 Visual Studio 内部快速触发的解决方案。
我正在寻找针对此类场景执行代码生成的最佳方法。 反射?码匠? T4模板?带有宏的 Resharper Live 模板?
我期待看到一些很棒的答案:)
To create our test data, we use the following variation of the Builder pattern (simplified example!):
Sample class:
public class Person
{
public string Name { get; set; }
public string Country { get; set; }
}
The builder:
public class PersonBuilder
{
private string name;
private string country;
public PersonBuilder()
{
SetDefaultValues();
}
private void SetDefaultValues()
{
name = "TODO";
country = "TODO";
}
public Person Build()
{
return new Person
{
Name = name,
Country = country
};
}
public PersonBuilder WithName(string name)
{
this.name = name;
return this;
}
public PersonBuilder WithCountry(string country)
{
this.country = country;
return this;
}
}
NOTE: The context of the example itself is not relevant. The important thing here is how in the example, the a builder class like PersonBuilder can completely be generated by looking at the entity class (Person) and applying the same pattern - see below.
Now imagine that the person class has 15 properties instead of 2. It would take some monkeywork to implement the builder class, while theoretically, it could automatically be generated from the Person class. We could use code generation to quickly set up the builder class, and add custom code later if needed.
The code generation process would have to be aware of the context (name and properties of the person class), so simple text-based code generation or regex magic doesn't feel right here. A solution that is dynamic, not text-based and can be triggered quickly from inside visual studio is preferred.
I'm looking for the best way to perform code generation for scenarios like this.
Reflection? Codesmith? T4 templates? Resharper Live templates with macros?
I'm looking forward to see some great answers :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
T4 解决方案是一个良好的 Visual Studio 集成选项。您可以在 T4 模板内使用反射来实际生成代码。
The T4 solution is a well Visual Studio integrated option. You can use reflection inside the T4 template to actually generate the code.
我们在 CodeSmith Generator 5.x 中添加了一项功能,允许您生成现有代码。请查看文档在这里。您还可以在 CodeSmith 生成器模板中使用反射或任何 .NET 库。
谢谢
——布莱克·尼米斯基
We added a feature in CodeSmith Generator 5.x that allows you to generate off of existing code. Please take a look at that documentation here. Also you can use reflection or any .NET library in a CodeSmith Generator Template.
Thanks
-Blake Niemyjski
如果仅用于测试,请考虑像 RhinoMocks 这样的模拟框架:
这样您的构建器就可以根据您的需求不断发展。此外,您不需要更改构建方法。只需添加“WithX”方法即可。
If it is for test only, consider a mocking framework like RhinoMocks:
This way your builder can evolve along with your need. Further, you don't need to change your Build method. Just add "WithX" methods.
了解 ABSE 建模方法及其 IDE,AtomWeaver. ABSE 是一个基于模板的建模和代码生成框架,其中模型(与 UML 或 MDA 无关)是通过应用“构建块”(原子)创建的。这些 Atom 是模板/程序混合体,并且具有上下文感知能力:Atom 可以根据其在树上的位置以及某些 Atom 的存在/不存在来生成代码。
模型主机(在本例中为 AtomWeaver)将“执行”模型以获得所需的源代码。模型可以是“源”:根据需要多次更改模型并重新生成。
AtomWeaver 未集成到 Visual Studio 中,但可以毫无问题地与它一起使用。
Have a look into the ABSE modeling approach and its IDE, AtomWeaver. ABSE is a template-based modeling and code generation framework, where a model (has nothing to do with UML or MDA) is created by applying "building blocks" (Atoms). These Atoms are template/program hybrids and are context-aware: an Atom can generate code according to its placement on the tree and on the presence/absence of certain Atoms.
The model host (AtomWeaver in this case) will "execute" the model in order to obtain the desired source code. The model can be "the source": change the model and regenerate as many times as necessary.
AtomWeaver is not integrated into Visual Studio, but can work alongside it without any problems.