Как сгенерировать код на основе другого класса? - PullRequest
9 голосов
/ 22 марта 2011

Для создания наших тестовых данных мы используем следующий вариант шаблона 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. Для реализации класса builder потребуется некоторая работа с обезьянами, хотя теоретически он может автоматически генерироваться из класса Person. Мы могли бы использовать генерацию кода, чтобы быстро настроить класс построителя, и добавить собственный код позже, если это необходимо.

Процесс генерации кода должен был бы учитывать контекст (имя и свойства класса person), поэтому простая генерация кода на основе текста или магия регулярных выражений здесь не чувствуются. Предпочтительным является динамическое, не основанное на тексте решение, которое можно быстро запустить из Visual Studio.

Я ищу лучший способ выполнить генерацию кода для подобных сценариев. Отражение? CodeSmith? Шаблоны Т4? Resharper Live шаблоны с макросами?

Я с нетерпением жду удачных ответов :)

Ответы [ 4 ]

2 голосов
/ 23 марта 2011

Мы добавили функцию CodeSmith Generator 5.x , которая позволяет генерировать существующий код.Пожалуйста, посмотрите на эту документацию здесь .Также вы можете использовать отражение или любую библиотеку .NET в шаблоне генератора CodeSmith.

Спасибо -Blake Niemyjski

2 голосов
/ 22 марта 2011

Решение T4 - это хорошо интегрированный вариант Visual Studio.Вы можете использовать отражение внутри шаблона T4 для фактического генерирования кода.

0 голосов
/ 24 марта 2011

Ознакомьтесь с подходом моделирования ABSE и его IDE, AtomWeaver . ABSE - это основанная на шаблонах инфраструктура моделирования и генерации кода, в которой модель (не имеющая ничего общего с UML или MDA) создается с применением «строительных блоков» (Atoms). Эти атомы являются гибридами шаблонов / программ и учитывают контекст: атом может генерировать код в соответствии с его расположением в дереве и наличием / отсутствием определенных атомов.

Хост модели (в данном случае AtomWeaver) будет «выполнять» модель для получения желаемого исходного кода. Модель может быть «источником»: измените модель и восстановите столько раз, сколько необходимо.

AtomWeaver не интегрирован в Visual Studio, но может работать вместе с ним без проблем.

0 голосов
/ 23 марта 2011

Если это только для теста, рассмотрите модель-макет, например 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».

...