开发者

How to generate code based on another class?

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 wou开发者_运维知识库ld 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 :)


The T4 solution is a well Visual Studio integrated option. You can use reflection inside the T4 template to actually generate the code.


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


If it is for test only, consider a mocking framework like 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; 
    }

}

This way your builder can evolve along with your need. Further, you don't need to change your Build method. Just add "WithX" methods.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜