Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically generating extensions to partial classes in visual studio

Here's what I'd like to do.

I want to write POCO classes like this:

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

preferably in arbitrary files in my solution (the [AutoExtend] attribute is something I just made up to identify the classes of interes).

I want the build process to start by (a) looking for these AutoExtend classes in my source code and (b) automatically generate extensions like this:

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

before compiling the solution.

Does anyone know how best to do this? I imagine Roslyn is the way to go, but I'm open to advice. Ideally, I'd like a solution which requires zero extra "plumbing" on the part of the user other than the AutoExtend attribute.

(In case anyone is interested, I'm writing a domain specific language in terms of C# classes with overloaded operators and the above would make the DSL substantially more comfortable to use.)

like image 669
Rafe Avatar asked Jun 05 '26 13:06

Rafe


1 Answers

As suggested in the comments, it's quite feasible with T4.

With regard to transforming on build, you can do it with a <TransformOnBuild> property in the .csproj file. see this question, in particular @Cheburek's answer. There is more information on MSDN.

Then to locate the classes with the AutoExtend attribute you'd need to use EnvDTE instead of reflection, because any existing assembly would be out of date.

Something like:

<#
// 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...
          <#
          } 
          #>
        }
<#          
        }
    }
}
#>
like image 180
shamp00 Avatar answered Jun 08 '26 03:06

shamp00



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!