在Visual Studio中自动生成分部类的扩展

本文关键字:扩展 自动生成 Visual Studio | 更新日期: 2023-09-27 18:30:34

这就是我想做的。

我想像这样编写 POCO 类:

[AutoExtended]
public partial class Foo {
    public int Bar;
    public string Baz;
}

最好在我的解决方案中的任意文件中([AutoExtend]属性是我刚刚为了识别 interes 类而编造的)。

我希望构建过程从 (a) 在我的源代码中查找这些AutoExtend类开始,并且 (b) 自动生成如下扩展:

public partial class Foo {
    public static SomeType<int> Bar(Foo x) { ... };
    public static SomeOtherType<string> Baz(Foo x) { ... };
}

在编译解决方案之前。

有谁知道如何最好地做到这一点? 我想罗斯林是要走的路,但我愿意接受建议。 理想情况下,我想要一个解决方案,除了 AutoExtend 属性之外,用户不需要额外的"管道"。

(如果有人感兴趣,我正在根据带有重载运算符的 C# 类编写一种特定于域的语言,上述内容将使 DSL 使用起来更加舒适。

在Visual Studio中自动生成分部类的扩展

正如评论中所建议的,使用 T4 是相当可行的。

关于生成时转换,可以使用 .csproj 文件中的 <TransformOnBuild> 属性执行此操作。 看到这个问题,特别是@Cheburek的答案。有关于 MSDN 的更多信息。

然后,若要查找具有 AutoExtend 属性的类,需要使用 EnvDTE 而不是反射,因为任何现有程序集都将过期。

像这样:

<#
// 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 attributes this method is decorated with
        var allAttributes = VisualStudioHelper.GetAllCodeElementsOfType(codeClass.Attributes, vsCMElement.vsCMElementAttribute, false);
        // check if the SomeProject.AutoExtendedAttribute is present
        if (allAttributes.OfType<EnvDTE.CodeAttribute>()
                         .Any(att => att.FullName == "SomeProject.AutoExtended"))
        {
        #>
        // this class has been generated
        public partial class <#= codeClass.FullName #>
        {
          <#
          // now get all methods implemented by the class
          var allFunctions = VisualStudioHelper.GetAllCodeElementsOfType(codeClass.Members, EnvDTE.vsCMElement.vsCMElementFunction, false);
          foreach(EnvDTE.CodeFunction function in allFunctions)
          {
          #>
              public static <#= function.FullName #> etc...
          <#
          } 
          #>
        }
<#          
        }
    }
}
#>