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.)
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...
<#
}
#>
}
<#
}
}
}
#>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With