How to get T4 in VS2010 to iterate over class' properties

痞子三分冷 提交于 2019-12-06 13:43:43
John Farrell

This is really hard as T4 templates and reflection don't play nice together.

See my answer to a similar, possible duplicate, question here:

Generate columnheaders based on the DisplayName attribute?

Update:

I don't need to check my answer, I have gone down this path and found reflection + t4 templates to be problematic. The banal example provided by the other answerer doesn't reflect the true complexity of the task the questioner is trying to accomplish. Try using a more realistic reflection target, like custom code, rather than a .NET class.

The reason why is clearly explained in the links I provided but since its easier to vote me down before reading links I'll post this here:

"An obvious first choice for accessing .NET metadata is Reflection. Built into .NET base class library, this API provides access to metadata of .NET types. Unfortunately, Reflection is optimized for code execution. One particular limitation makes it ill-suited for code generation - an assembly loaded using Reflection can only be unloaded with its AppDomain. Because T4 templates are compiled into .NET assemblies and cached to improve performance of code generation, using Reflection to access the component assembly causes T4 to lock it. This prevents you from changing/recompiling the component until you close and reopen the solution. While you can certainly live with this annoyance, it would be nice to avoid it."

tsinik

Use Reflection in the tags.

Something like:

<#foreach (PropertyInfo info in myObject.GetType().GetProperties()){#>
    // do what you want with or any other property of info <#=info.Name#>
<#}#>

try the tuturials here msdn

<#@ template debug="false" language="C#" #>
<#@ output extension=".txt" #>
<#@ assembly name="System.Xml"#>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Reflection" #>

<#
XmlDocument doc = new XmlDocument();
foreach (PropertyInfo info in doc.GetType().GetProperties()){#>
    <#=info.Name#>
<#}#> 

will print all properties of xmldocument

If the assembly you are reflecting over is part of your project (as the original question-raiser mentioned) then you will experience the locking as mentioned.

There is an interim solution as part of Oleg Sych's T4Toolbox codeplex project (http://t4toolbox.codeplex.com/), which provides a new VolatileAssembly directive which copies the assembly before loading it.

We're currently working on fixing this in the core T4 engine as soon as practical.

However, if you want to work with the code in your project, you may not want to deal with the compiled assembly, but the source code on disk, in which case the CodeModel inside VS is another option (if you can live with templates only running inside VS at design time).

There is an example of this at http://www.olegsych.com/2008/07/t4-template-for-generating-sql-view-from-csharp-enumeration/

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!