перебрать класс для свойств - PullRequest
6 голосов
/ 15 марта 2012

Я пытаюсь написать шаблон 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]

любые советы о том, где яиду не так?кажется, что он разыгрывается как ком-объект ... может быть, это неправильно?

РЕДАКТИРОВАТЬ:

ссылки:

http://www.olegsych.com/2008/07/t4-template-for-generating-sql-view-from-csharp-enumeration/

Как заставить T4 в VS2010 перебирать свойства класса

Код:

<# 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;
}

Ответы [ 4 ]

4 голосов
/ 15 марта 2012

Чтобы получить список свойств в классах / структурах, содержащихся в данном исходном файле, вы можете сделать следующее (вы можете легко получить имя класса и т. Д. С помощью 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 голос
/ 15 марта 2012

нашел эту статью.кажется, есть много ответов: http://www.codeproject.com/Articles/42036/Project-Metadata-Generation-using-T4

0 голосов
/ 24 июня 2017
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>();
0 голосов
/ 15 марта 2012

Вы должны импортировать свою собственную сборку, чтобы иметь возможность доступа к свойствам типа через отражение. Шаблоны T4 выполняются в контексте Visual Studio, поэтому вы не можете получить доступ к типам вашего проекта.

Импортируйте сборку нужного типа с помощью директивы сборки. Вы можете использовать макросы для поиска вашей сборки (например, $ (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 использовали один домен приложения для загрузки сборки с директивой сборки. Поэтому вам приходилось перезапускать Visual Studio каждый раз, когда сборка обновлялась. С SP1 VS использует новый домен приложения для каждого преобразования T4.

...