我正在尝试编写一个T4模板来迭代项目文件夹(指定)并根据这些属性生成一个js文件。
我能够将我的第一个类文件作为ProjectItem返回(作为System .__ ComObject返回)
我看到名称正确返回(“MyReadModel.cs”)
Public Class MyReadModel{
Public string MyName { get; set; }
public int MyAge { get; set;}
}
现在我正在努力将属性退出其中。 该文件的FileCodeModel为System .__ ComObject。 我找不到任何房产。
我尝试了以下操作:
projectItem.GetType().GetProperties()
但返回System.Reflection.PropertyInfo [0]
关于我哪里出错的任何提示?它看起来像是一个com对象...也许这是错的?
编辑:
参考:
http://www.olegsych.com/2008/07/t4-template-for-generating-sql-view-from-csharp-enumeration/
How to get T4 in VS2010 to iterate over class' properties
代码:
<# Prepare(this); #>
<# foreach(ProjectItem pi in FindProjectItemsIn(CurrentProject.ProjectItems.Item("Commands"))) { #>
<# WriteLine("found " + pi); #>
<# } #>
<#+
static DTE Dte;
static Dictionary<string, ResultTypeInfo> ResultTypes;
static TextTransformation TT;
static Microsoft.CSharp.CSharpCodeProvider codeProvider = new Microsoft.CSharp.CSharpCodeProvider();
static Project CurrentProject;
IList<ProjectItem> FindProjectItemsIn(ProjectItem start) {
var list = new List<ProjectItem>();
FindProjectItemsIn(start, list);
return list;
}
static bool IsFolder1(ProjectItem item) {
return (item.Kind == Constants.vsProjectItemKindPhysicalFolder);
}
void FindProjectItemsIn(ProjectItem start, IList<ProjectItem> list) {
foreach(ProjectItem item in start.ProjectItems) {
if(IsFolder1(item)) {
FindProjectItemsIn(item, list);
continue;
}
list.Add(item);
}
}
void Prepare(TextTransformation tt) {
TT = tt;
// Get the DTE service from the host
var serviceProvider = Host as IServiceProvider;
if (serviceProvider != null) {
Dte = serviceProvider.GetService(typeof(SDTE)) as DTE;
}
var projectItem = Dte.Solution.FindProjectItem(Host.TemplateFile);
CurrentProject = projectItem.ContainingProject;
}
答案 0 :(得分:4)
为了获取给定源文件中包含的类/结构中的属性列表,您可以执行以下操作(您可以通过使用CodeClass轻松获取类名等):
private IList<CodeProperty> GetProperties(string csFile)
{
ProjectItem projectItem = TransformationContext.FindProjectItem(csFile);
FileCodeModel codeModel = projectItem.FileCodeModel;
var propertyList = new List<CodeProperty>();
FindProperties(codeModel.CodeElements, propertyList);
return propertyList;
}
private void FindProperties(CodeElements elements, IList<CodeProperty> properties)
{
foreach (CodeElement element in elements)
{
CodeProperty property = element as CodeProperty;
if (property != null)
{
properties.Add(property);
}
FindProperties(element.Children, properties);
}
}
答案 1 :(得分:1)
答案 2 :(得分:0)
您必须导入自己的程序集才能通过反射访问类型属性。 T4模板在Visual Studio的上下文中执行,这就是您无法访问项目类型的原因。
因此,使用assembly-directive导入具有所需类型的程序集。您可以使用宏来查找程序集(例如$(SolutionDir))。然后,您可以导入命名空间并使用您自己的程序集中的类型。
可能是这样的:
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ assembly name="$(SolutionDir)YourProject\bin\debug\YourAssembly.dll" #>
<#@ import namespace="YourNamespace" #>
<#
Type typeInfo = typeof(yourType);
foreach (PropertyInfo propertyInfo in yourType.GetProperties())
{#>
<#=propertyInfo.Name#>
<#}#>
强烈建议将其与Visual Studio 2010 SP 1(或更高版本)一起使用。以前的Visual Studio版本使用单个应用程序域来使用assembly-directive加载程序集。因此,每次更新程序集时都必须重新启动Visual Studio。使用SP1 VS为每个T4转换使用新的appdomain。
答案 3 :(得分:0)
private static IEnumerable<CodeElement> Flatten(CodeElements elements) {
foreach (CodeElement2 child in elements) {
yield return child;
foreach (var i in Flatten( child.Children )) {
yield return i;
}
}
}
...
var imports = Flatten( fileCodeModel.CodeElements )
.Where( i => i.Kind == vsCMElement.vsCMElementImportStmt )
.Cast<CodeImport>();