如何在T4中使用.net反射?

15

我有一个包含文本模板的C#项目。我希望这个模板可以通过反射C#类来生成一些SQL。

如何使用T4访问当前项目的内容?是否可能访问反射,或者只能访问必须进行解析的原始源代码?

谢谢!


2
重复的问题:https://dev59.com/0XM_5IYBdhLWcg3w9oMA? - Paolo Tedesco
3个回答

5

如何使用T4访问当前项目的内容?

一种方法是使用EnvDTE COM组件。在Google中搜索T4和EnvDTE应该会带回大量示例。

是否可能,并且如果可能,Reflection是否可用,还是必须访问原始源代码,然后进行解析?

Reflection在T4中肯定可用。它的工作方式大多与您预期的相同。

Oleg Sych有许多关于常见T4使用场景的优秀博客文章,但还有很多其他T4资源可用。


@Maslow:每当你在Visual Studio中从T4以任何方式访问DLL(反射或非反射),该DLL都会被锁定,而且不容易在不关闭Visual Studio并重新打开它的情况下进行更改。我个人认为这是Visual Studio T4实现中的一个错误(Microsoft可能会认为这是一个缓存功能)。EnvDTE也会出现锁定问题,但您没有尝试更改该DLL,因此您不会注意到它已被锁定,也不重要。这个锁定问题与反射无关,即使您不使用反射,它也会发生。 - Michael Maddox
@Michael - Oleg Sync明确表示不要在T4中使用反射。我不知道原因,也许那里的上下文有所不同,但这就是我在这个帖子中添加的内容,我应该找到链接并将其包含在最初的评论中。 - Maslow
@Maslow:T4将程序集锁定在内存中。想象一下,你有一个模板,在其中获取最近构建的dll并开始反射它。下次尝试构建时,会失败,因为该文件已被锁定,无法覆盖。幸运的是,这种行为在SP1中正在改变,因此在T4模板中进行反射将没有问题。 - user1228
1
反射在Vs2010 SP1中似乎变得可行了。 - Maslow
T4中的反射问题得到了特别解决。http://blogs.msdn.com/b/t4/archive/2011/03/25/vs2010-sp1-t4-improvements-summary.aspx - Dave Swersky
显示剩余2条评论

4
除了锁定问题之外,要小心在T4模板中使用反射。VS2010中的模板生成器针对4.0版本的框架运行,因此如果您为3.5或更低版本生成代码,则可能引入不需要的依赖项。
我刚刚通过使用反射来决定是否为各种BCL类型生成无参数或有参数调用ToString方法的方式发现了这个问题。TimeSpan在2.0中仅有ToString()方法,但在4.0中添加了ToString(string)方法:P

0

虽然这并不能解决锁定问题(尽管我听说VS2010可以),但您可以尝试将dll复制到临时位置,然后只使用该复制的程序集。

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".txt" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.IO" #>
<#    
var newFileName = System.IO.Path.GetTempFileName();
System.IO.File.Copy(@"C:\Development\CustomAssembly.dll",newFileName,true);

var assembly = Assembly.LoadFrom(newFileName);
var type = assembly.GetType("CustomAssembly.DummyClass");   
#>
<#=newFileName#>
<#=type#>

是的,这样可以避免锁定原始文件,但是AppDomain只会加载程序集一次,无论文件名如何它都不会再次加载。我尝试在新的应用域中加载该文件以便在完成后卸载它,但是一直不成功。 - Jason Kleban
使用底层流将程序集加载为字节数组。 - sll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接