2013-04-24 13 views
10

Vorrei ottenere un elenco di tutti i metodi pubblici nel mio progetto che sono decorati utilizzando MyAttribute utilizzando T4/EnvDTE.Ottieni tutti i metodi decorati con un attributo specifico utilizzando T4/EnvDTE

So che questo può essere fatto con la riflessione, ma non voglio caricare l'assembly e riflettere su di esso in un modello T4, piuttosto, voglio usare i file di codice esistenti come sorgente.

Quello che segue è codice standard che ho trovato su internet che ottiene un riferimento al progetto corrente

<#@ template debug="true" hostspecific="true" language="C#" #> 
<#@ assembly name="EnvDTE" #> 
<#@ assembly name="System.Core.dll" #> 
<#@ import namespace="System.Linq" #> 
<#@ import namespace="System.Collections.Generic" #> 
<#@ import namespace="System.IO" #> 
<#@ output extension=".cs" #> 

<# 
    IServiceProvider _ServiceProvider = (IServiceProvider)Host; 
    if (_ServiceProvider == null) 
     throw new Exception("Host property returned unexpected value (null)"); 

    EnvDTE.DTE dte = (EnvDTE.DTE)_ServiceProvider.GetService(typeof(EnvDTE.DTE)); 
    if (dte == null) 
     throw new Exception("Unable to retrieve EnvDTE.DTE"); 

    Array activeSolutionProjects = (Array)dte.ActiveSolutionProjects; 
    if (activeSolutionProjects == null) 
     throw new Exception("DTE.ActiveSolutionProjects returned null"); 

    EnvDTE.Project dteProject = (EnvDTE.Project)activeSolutionProjects.GetValue(0); 
    if (dteProject == null) 
     throw new Exception("DTE.ActiveSolutionProjects[0] returned null"); 

#> 

risposta

13

vorrei confermare il vostro piano per utilizzare EnvDTE per ottenere informazioni di progettazione sulle classi del vostro progetto e metodi. Secondo me è più affidabile che rischiare di riflettere un'assemblea obsoleta dello stesso progetto.

Dal momento che avete già ottenuto il progetto attuale della soluzione ora è necessario utilizzare l'Visual Studio CodeModel per iterare le vostre classi e dei loro metodi, ecc So che questo può essere piuttosto fastidioso, ma ho trovato un modello di .ttinclude riutilizzabile gratuito che fornisce metodi che facilitano l'accesso al CodeModel. Potresti voler dare un'occhiata allo tangible's T4 Editor. È gratuito e viene fornito con una galleria di modelli gratuita che contiene uno "Assistente di automazione di Visual Studio tangibile". Usando questo modello il tuo codice risultante potrebbe essere il seguente:

<# 
// get a reference to the project of this t4 template 
var project = VisualStudioHelper.CurrentProject; 

// get all class items from the code model 
var allClasses = VisualStudioHelper.GetAllCodeElementsOfType(project.CodeModel.CodeElements, EnvDTE.vsCMElement.vsCMElementClass, false); 

// iterate all classes 
foreach(EnvDTE.CodeClass codeClass in allClasses) 
{ 
    // get all methods implemented by this class 
    var allFunctions = VisualStudioHelper.GetAllCodeElementsOfType(codeClass.Members, EnvDTE.vsCMElement.vsCMElementFunction, false); 
    foreach(EnvDTE.CodeFunction function in allFunctions) 
    { 
     // get all attributes this method is decorated with 
     var allAttributes = VisualStudioHelper.GetAllCodeElementsOfType(function.Attributes, vsCMElement.vsCMElementAttribute, false); 
     // check if the System.ObsoleteAttribute is present 
     if (allAttributes.OfType<EnvDTE.CodeAttribute>() 
         .Any(att => att.FullName == "System.ObsoleteAttribute")) 
     { 
     #><#= function.FullName #> 
<#   
     } 
    } 
} 
#> 
+0

Non vedo "tangibile Automazione di Visual Studio Helper" nell'elenco dei modelli di VS. – Omar

+0

Lo vedo ora. Devi aprire un file '.tt' a quel punto comparirà il menu' Tangibile T4' con i menu standard. È la prima voce di menu. Lasciami fare un tentativo. – Omar

+2

Riesco a vedere Visual Studio Automation Helper nel modello Gallary ma non vi è alcun riferimento a VisualStudioHelper. Esiste una classe chiamata DteHelper ma non ha i metodi indicati nel tuo esempio come GetAllCodeElementsOfType. –

Problemi correlati