11

I'd like to get a list of all public methods in my project that are decorated using MyAttribute using T4/EnvDTE.

I know this can be done with reflection, but I don't want to load the assembly and reflect over it in a T4 template, rather, I want to use the existing code files as the source.

The following is boilerplate code I found on the internet that gets a reference to the current project

<#@ 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");

#>
Dariusz Woźniak
  • 9,640
  • 6
  • 60
  • 73
Omar
  • 39,496
  • 45
  • 145
  • 213

1 Answers1

14

I would like to confirm your plan to use EnvDTE to gain design-time information about your project's classes and methods. In my opinion it's more reliable than risking to reflect an outdated assembly of the same project.

Since you already got the current project of your solution you should now use the Visual Studio CodeModel to iterate your classes and their methods etc. I know this can be pretty annoying, but I found a free reusable .ttinclude template that provides you with methods easing the access to the CodeModel. You might want to check out tangible's T4 Editor. It's free and ships with a free template gallery that contains one named "tangible Visual Studio Automation Helper". Using this template your resulting code could look like this:

<#
// 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 #>
<#          
        }
    }
}
#>
Nico
  • 2,120
  • 16
  • 20
  • I don't see 'tangible Visual Studio Automation Helper' in VS's templates list. – Omar Apr 25 '13 at 14:24
  • I see it now. You have to open a `.tt` file at which point a `Tangible T4` menu will appear with the standard menus. It's the first menu item. Let me give this a shot. – Omar Apr 25 '13 at 14:36
  • 2
    I can see Visual Studio Automation Helper in the template Gallary but there is no reference to VisualStudioHelper anywhere. There is a class called DteHelper but it doe snot have the methods indicated in your example such as GetAllCodeElementsOfType. – Code Uniquely Jun 30 '13 at 12:15
  • Make sure you are using the "tangible Visual Studio Automation Helper" template. There's another template named "Visual Studio Automation Helper" that is not as powerful as tangible's. Does this solve your issue? – Nico Jul 01 '13 at 07:02