Search code examples
c#.netextension-methodscodedom

Creating extension method using CodeDOM


I'm trying to create an extension method using CodeDOM. There doesn't seem to be any support for them and using ExtensionAttribute (which C# uses internally to mark extension methods) is not allowed.

It's possible to use a trick to specify the this modifier, but how do I make the containing class static, so that the code actually compiles?

Since static is a C# concept, it's not exposed through the CodeDOM API. And setting TypeAttributes to TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.Public doesn't work, because

an abstract class cannot be sealed or static

How do I make the extension method to compile?


Solution

  • I'm pretty sure you're looking for:

    var staticClass = new CodeTypeDeclaration("Extensions")
        {
            Attributes = MemberAttributes.Public|MemberAttributes.Static
        };
    

    However, this appears not to work. Interestingly enough:

    provider.Supports(GeneratorSupport.StaticConstructors);
    // True
    
    provider.Supports(GeneratorSupport.PublicStaticMembers);
    // True
    

    But yet when you go and output it, no changes even though the Attributes property clearly changes from 0x00005002 to 0x00006003.

    Per Microsoft Connect this is not possible:

    Thanks for reporting this. Unfortunately, it doesn't look like we can support static classes for CodeDom.

    The reason is that one of the design goals of CodeDom is to be language-independent, so that any code generated for one language can easily be generated for a different language. While static classes are used often in C#, VB does not support them. Therefore, adding support for static classes will mean that some code that can compile for C# won't be compilable for VB, which goes against our goals.

    While we can't act on this issue, we ask that you please continue to provide feedback in the future to help us improve.


    A dirty workaround:

    var type = new CodeTypeDeclaration("Extensions");
    type.Attributes = MemberAttributes.Public;
    type.StartDirectives.Add(
        new CodeRegionDirective(CodeRegionMode.Start, "\nstatic"));
    type.EndDirectives.Add(
        new CodeRegionDirective(CodeRegionMode.End, String.Empty));
    

    Produces:

    #region
    static
    public class Extensions
    {
    }
    #endregion
    

    Which compiles.