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

Visual studio 如何基于另一个类生成代码?,visual-studio,reflection,code-generation,resharper,codesmith,Visual Studio,Reflection,Code Generation,Resharper,Codesmith,为了创建测试数据,我们使用以下生成器模式的变体(简化示例!): 示例类: public class Person { public string Name { get; set; } public string Country { get; set; } } 建筑商: public class PersonBuilder { private string name; private string country; public PersonBuilder(

为了创建测试数据,我们使用以下生成器模式的变体(简化示例!):

示例类:

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;
    }
}
注意:示例本身的上下文并不相关。这里重要的是,在这个示例中,如何通过查看实体类(Person)并应用相同的模式来完全生成像PersonBuilder这样的构建器类-请参见下文

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

代码生成过程必须知道上下文(person类的名称和属性),因此简单的基于文本的代码生成或regex-magic在这里感觉不太好。首选动态的、非文本的、可从VisualStudio内部快速触发的解决方案

我正在寻找为这样的场景执行代码生成的最佳方法。 反射密码匠?T4模板?使用宏重新还原活动模板


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

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

< P>如果仅用于测试,请考虑类似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; 
    }

}
内部类PersonBuilder
{
私有MockRepository\u MockRepository;
私人IPerson(个人),;
公共人事建设者()
{
_mockRepository=新建mockRepository();
_person=_mockRepository.Stub();
}
带名称的公共PersonBuilder(字符串名称)
{
_person.Name=姓名;
归还这个;
}
带国家/地区的公共人员生成器(字符串国家/地区)
{
_个人。国家=国家;
归还这个;
}
公共IPerson构建()
{
_mockRepository.ReplayAll();
返回人;
}
}
这样,您的构建器可以随着您的需求而发展。此外,您不需要更改构建方法。只需添加“WithX”方法

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

谢谢 -Blake Niemyjski

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

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


AtomWeaver没有集成到Visual Studio中,但可以毫无问题地与之协同工作。

我们已经在单元测试中广泛使用了模拟,但我从未想过为此使用模拟:)。我认为这将是解决这个特殊问题的一个很好的方法,但不是一般问题,它的范围比测试更广。不过还是要感谢你的回答!