9

要创建我们的测试数据,我们使用了Builder模式的以下变化(简化的例子!):如何基于另一个类生成代码?

Sample类:

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个。它需要一些monkeywork来实现构建器类,而理论上它可以自动从Person类生成。我们可以使用代码生成来快速设置构建器类,并在需要时添加自定义代码。

代码生成过程必须知道上下文(人类的名称和属性),所以简单的基于文本的代码生成或正则表达式的魔法不会感觉就在这里。一个动态的解决方案,不是基于文本的,可以从Visual Studio内部快速触发。

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

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

回答

2

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

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

} 

这样,你的建设者可以与您一起需要进化。此外,你不需要改变你的构建方法。只需添加“WithX”方法即可。

+0

我们已经在我们的单元测试中广泛地使用了mocking,但是我从来没有想过为此使用mock :)。我认为这将是一个很好的解决这个问题的方法,但不是一般问题,它比测试更广泛。但是,非常感谢这个答案! – 2011-03-27 12:12:46

2

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

感谢 -Blake Niemyjski

0

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

模型主机(在这种情况下是AtomWeaver)将“执行”模型以获得所需的源代码。该模型可以是“来源”:根据需要更改模型并重新生成多次。

AtomWeaver没有集成到Visual Studio中,但可以在没有任何问题的情况下一起工作。

相关问题