通过反射在同一组件生成code [英] Generate code through Reflection over the same assembly

查看:120
本文介绍了通过反射在同一组件生成code的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开始涉足T4和先沿pretty的病好,但后来遇到了一个问题,实际上是pretty的明显的,可能不是解决的,但也许有,我只是缺乏经验的方式知道或看到的。

I have started dabbling in T4 and first got along pretty well, but then ran into an issue that's actually pretty obvious and might not be solvable, but maybe there is a way that I just lack the experience to know or see.

考虑下面的类:

public class T4Test : CodeActivity
{
    protected override void Execute(CodeActivityContext context)
    {
    }

    [Input("InX")]
    public InArgument<string> InX { get; set; }

    [Output("OutX")]
    public OutArgument<string> OutX { get; set; }
}

我想这是输出:

I want this as the output:

public class ActivityWrapper
{
    private readonly T4Test _activity;
    private readonly ActivityContext _context;

    public ActivityWrapper(T4Test activity, ActivityContext context)
    {
        this._activity = activity;
        this._context = context;
    }

    public string InX
    {
        get { return this._activity.InX.Get(this._context); }
    }

    public string OutX
    {
        get { return this._activity.OutX.Get(this._context); }
        set { this._activity.OutX.Set(this._context, value); }
    }
}

我想通了反思的东西,我需要的,我知道T4 code应该是什么样子,但是有一个问题:我需要在同一个项目的 T4Test 类。但是,加载程序集,并反映过来呢,就需要编译 - 但当然,如果我打算修改同一程序集的code,这是一个有点困难。 (我猜NCrunch并没有简化的东西。)

I have figured out the Reflection stuff I need, and I know what the T4 code should look like, but there's one problem: I need it in the same project as the T4Test class. However, to load the assembly and reflect over it, it needs to be compiled - but of course that's a bit difficult if I intend to modify that same assembly's code. (And I guess NCrunch doesn't simplify things.)

现在这里的,我希望可能仍然有可能解决这个事情:

Now here's the things that I hope might still make it possible to solve this:

  • 在该项目的将会的编译没有生成的类。这是因为类将实现由IoC容器-resolved接口将自动注册/。这也是不可测试,无论如何,因为 ActivityContext 不能被嘲笑。
  • 出于这个原因,它不必须在那里或​​纠正所有的时间。我只需要能够说现在产生这种之前,实际上提供的DLL。
  • 出于同样的原因,我也不在乎T4的模板实际上是否坐在项目 - 只要所生成的文件结束了在项目(尽管无需另一个项目为模板,构建PostBuild事件复制的.cs 文件来解决)。
  • 要为precise,它甚至不需要是T4。如果有做任何其他可行的方法,我会很高兴的使用为好。
  • The project will compile without the generated class. This is because the class will implement interfaces that will be auto-registered/-resolved by an IoC container. It is also not testable anyway, because ActivityContext can't be mocked.
  • For that reason it doesn't have to be there or correct all the time. I just need to be able to say "generate this now" before actually delivering the DLL.
  • For the same reason I also don't care whether the T4 template actually sits in the project - as long as the generated file ends up in the project (though without needing another project for the template and constructing PostBuild events to copy a .cs file around).
  • To be precise, it doesn't even need to be T4. If there's any other feasible way to do it, I'll be happy to use that as well.

有什么办法来实现这一目标? (而且是,即使不够清楚?)

Is there any way to achieve this? (And was that even clear enough?)

推荐答案

T4Test.tt

<#@ include file="Activities.tt" #>
<#
var t4test = new Activity("T4Test")
{
    Input("InX"),
    Output("OutX"),
};
GenerateCode(t4test);
#>

Activities.tt

<#@ template language="C#" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#+
class Activity : IEnumerable<Property>
{
    private string name, wrapper;
    private List<Property> properties;
    public Activity(string name, string wrapper = null)
    {
        this.name = name;
        this.wrapper = wrapper ?? name + "Wrapper";
        this.properties = new List<Property>();
    }
    public void Add(Property property)
    {
        this.properties.Add(property);
    }
    public IEnumerator<Property> GetEnumerator()
    {
        return this.properties.GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
    public void GenerateCode()
    {
        // ...
    }
}
class Property
{
    private bool output;
    private string name, type;
    public Property(bool output, string name, string type)
    {
        this.output = output;
        this.name = name;
        this.type = type;
    }
}
Property Input(string name, string type = "string")
{
    return new Property(false, name, type);
}
Property Output(string name, string type = "string")
{
    return new Property(true, name, type);
}
void GenerateCode(params Activity[] activities)
{
    WriteLine("namespace Foo");
    WriteLine("{");
    PushIndent("   ");
    foreach (var activity in activities)
    {
        WriteLine("class " + activity.name);
        WriteLine("{");
        PushIndent("   ");
        // ...
        PopIndent();
        WriteLine("}");
    }
    PopIndent();
    WriteLine("}");
}
#>

这篇关于通过反射在同一组件生成code的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆