使用T4/EnvDTE获取用特定属性装饰的所有方法

本文关键字:属性 有方法 T4 EnvDTE 获取 使用 | 更新日期: 2023-09-27 18:10:48

我想获得我的项目中使用MyAttribute使用T4/EnvDTE装饰的所有公共方法的列表。

我知道这可以通过反射来完成,但是我不想在T4模板中加载程序集并对其进行反射,相反,我想使用现有的代码文件作为源。

下面是我在互联网上找到的样板代码,它获得了对当前项目的引用

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

使用T4/EnvDTE获取用特定属性装饰的所有方法

我想确认您使用EnvDTE来获取有关项目类和方法的设计时信息的计划。在我看来,这比冒险反映同一个项目的过时的集合更可靠。

既然你已经得到了你的解决方案的当前项目,你现在应该使用Visual Studio CodeModel来迭代你的类和它们的方法等。我知道这可能很烦人,但我发现了一个免费的可重用.ttinclude模板,它为您提供了简化访问CodeModel的方法。你可能想看看有形的T4编辑器。它是免费的,并附带一个免费的模板库,其中包含一个名为"有形的Visual Studio自动化助手"。使用此模板,生成的代码可能如下所示:

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