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中,但可以在沒有任何問題的情況下一起工作。