我已经开始涉足 T4,一开始相处得很好,但后来遇到了一个实际上非常明显并且可能无法解决的问题,但也许有一种方法我只是缺乏知道或看到的经验。
给定以下课程:
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; }
}
我想要这个作为输出:
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 代码应该是什么样子,但有一个问题:我需要它在与T4Test
班级。但是,要加载程序集并反映它,需要对其进行编译 - 但如果我打算修改同一程序集的代码,这当然有点困难。 (我猜 NCrunch 并没有简化事情。)
现在,我希望以下这些事情仍然可以解决这个问题:
- 该项目will编译时不带生成的类。这是因为该类将实现由 IoC 容器自动注册/解析的接口。无论如何它也是不可测试的,因为
ActivityContext
不能被嘲笑。
- 因此,它不必始终存在或正确。我只需要能够在实际交付 DLL 之前说“立即生成它”。
- 出于同样的原因,我也不关心 T4 模板是否实际位于项目中 - 只要生成的文件最终位于项目中(尽管不需要模板的另一个项目并构建 PostBuild 事件来复制
.cs
文件周围)。
- 准确来说,甚至不需要是T4。如果还有其他可行的方法,我也很乐意使用。
有什么办法可以实现这一点吗? (这足够清楚了吗?)
我想提出一种反映生成的程序集的替代方案,因为只有当项目成功构建并生成正确的输出(前提是程序集没有过时)时,转换 T4 才有效。
如果您使用主机特定的 T4 模板,您可以通过 EnvDTE 接口访问 Visual Studio 自动化模型。使用它,您可以遍历当前加载的 Visual Studio 解决方案的 CodeModel,而无需先构建它。
看看我对这个问题的回答:设计时反思 https://stackoverflow.com/questions/14134016/design-time-reflection/14402269#14402269。使用有形模板库中的免费模板的帮助,您可以在设计时轻松“反映”现有的类,并检测用所需属性装饰的属性:
<#
var project = VisualStudioHelper.CurrentProject;
// get all class items from the code model
var allClasses = VisualStudioHelper.GetAllCodeElementsOfType(project.CodeModel.CodeElements, EnvDTE.vsCMElement.vsCMElementClass, false);
// iterate all classes
foreach(EnvDTE.CodeClass codeClass in allClasses)
{
// iterate all properties
var allProperties = VisualStudioHelper.GetAllCodeElementsOfType(codeClass.Members, EnvDTE.vsCMElement.vsCMElementProperty, true);
foreach(EnvDTE.CodeProperty property in allProperties)
{
// check if it is decorated with an "Input"-Attribute
if (property.Attributes.OfType<EnvDTE.CodeAttribute>().Any(a => a.FullName == "Input"))
{
...
}
}
}
#>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)