如何基于另一个类生成代码?

时间:2011-03-22 14:08:39

标签: visual-studio reflection code-generation resharper codesmith

要创建我们的测试数据,我们使用Builder模式的以下变体(简化示例!):

示例类:

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;
    }
}

注意:示例本身的上下文不相关。这里重要的是如何在示例中,像PersonBuilder这样的构建器类可以通过查看实体类(Person)并应用相同的模式来完全生成 - 见下文。

现在假设person类有15个属性而不是2个。实现构建器类需要一些猴子工作,而理论上,它可以自动从Person类生成。我们可以使用代码生成来快速设置构建器类,并在以后需要时添加自定义代码。

代码生成过程必须知道上下文(人类的名称和属性),因此简单的基于文本的代码生成或正则表达式魔法在这里感觉不对。首选的是动态解决方案,而不是基于文本的解决方案,并且可以从视觉工作室内快速触发。

我正在寻找为此类场景执行代码生成的最佳方法。 反射? CodeSmith中? T4模板? Resharper Live模板与宏?

我期待看到一些很棒的答案:)

4 个答案:

答案 0 :(得分:2)

T4解决方案是一个很好的Visual Studio集成选项。您可以在T4模板中使用反射来实际生成代码。

答案 1 :(得分:2)

我们在CodeSmith Generator 5.x中添加了一项功能,允许您生成现有代码。请看一下documentation here。您还可以在CodeSmith Generator模板中使用反射或任何.NET库。

由于 -Blake Niemyjski

答案 2 :(得分:0)

如果仅用于测试,请考虑像RhinoMocks这样的模拟框架:

internal class PersonBuilder
{
    private MockRepository _mockRepository;
    private IPerson _person;

    public PersonBuilder()
    {
        _mockRepository = new MockRepository();
        _person = _mockRepository.Stub<IPerson>();
    }

    public PersonBuilder WithName(string name)
    {
        _person.Name = name;
        return this; 
    }

    public PersonBuilder WithCountry(string Country)
    {
        _person.Country= Country;
        return this;
    }

    public IPerson Build()
    {
        _mockRepository.ReplayAll();
        return _person; 
    }

}

通过这种方式,您的建筑师可以随着您的需求而发展。此外,您无需更改Build方法。只需添加“WithX”方法即可。

答案 3 :(得分:0)

查看ABSE建模方法及其IDE AtomWeaver。 ABSE是一个基于模板的建模和代码生成框架,其中通过应用“构建块”(Atoms)创建模型(与UML或MDA无关)。这些Atom是模板/程序混合并且是上下文感知的:Atom可以根据它在树上的位置以及某些Atom的存在/不存在来生成代码。

模型主机(在本例中为AtomWeaver)将“执行”模型以获取所需的源代码。模型可以是“源”:根据需要更改模型并重新生成。

AtomWeaver没有集成到Visual Studio中,但可以毫无问题地与它一起工作。