Iterate over a class for properties

I am trying to write a T4 template to iterate over a project folder (specified) and create a js file based on these properties.

I can return my first class file as ProjectItem (returned as System .__ ComObject)

I see that the name is being returned correctly ("MyReadModel.cs")

Public Class MyReadModel{ Public string MyName { get; set; } public int MyAge { get; set;} } 

Now I am trying to return properties from it. The file has a FileCodeModel as a System .__ ComObject. I can not find any properties.

I tried to do the following:

 projectItem.GetType().GetProperties() 

but returns System.Reflection.PropertyInfo [0]

any tips on where i'm wrong? it seems to be cast as a com object ... maybe this is wrong?

EDIT:

links:

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

the code:

 <# 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; } 
+6
source share
4 answers

To get the list of properties in the classes / structures contained in this source file, you can do the following (you can easily get the class name, etc. using 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); } } 
+4
source
+1
source

You need to import your own assembly in order to be able to access type properties through reflection. T4 templates run in the context of Visual Studio, so you cannot access the types of your project.

Therefore, import the assembly with the desired type using the assembly directive. You can use macros to find your assembly (e.g. $ (SolutionDir)). You can then import the namespace and use this type from your own assembly.

It could be something like this:

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

It is highly recommended that you use this with Visual Studio 2010 SP 1 (or later). Previous versions of Visual Studio used a single application domain to load the assembly using the assembly directive. Therefore, you had to restart Visual Studio every time the assembly was updated. With SP1, VS uses a new application for every T4 conversion.

0
source
 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
source

Source: https://habr.com/ru/post/910785/


All Articles