使用CodeDOM创建扩展方法

时间:2011-06-10 15:10:30

标签: c# .net extension-methods codedom

我正在尝试使用CodeDOM创建扩展方法。似乎没有对它们的任何支持,并且不允许使用ExtensionAttribute(C#内部用于标记扩展方法)。

可以使用a trick指定this修饰符,但如何创建包含类static,以便代码实际编译?

由于static是C#概念,因此不会通过CodeDOM API公开。将TypeAttributes设置为TypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.Public不起作用,因为

  

抽象类不能密封或静态

如何使扩展方法编译?

4 个答案:

答案 0 :(得分:6)

我很确定你在寻找:

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

然而,这似乎不起作用。有趣的是:

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

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

但是当你去输出它时,即使属性属性明显从0x00005002变为0x00006003,也没有变化。

Per Microsoft Connect this is not possible

  

感谢您报告此事。不幸的是,看起来我们不能支持CodeDom的静态类。

     

原因是CodeDom的设计目标之一是与语言无关,因此可以轻松地为不同语言生成为一种语言生成的任何代码。虽然静态类经常在C#中使用,但VB不支持它们。因此,添加对静态类的支持意味着一些可以为C#编译的代码将无法编译为VB,这违背了我们的目标。

     

虽然我们无法就此问题采取行动,但我们请您继续提供反馈,以帮助我们改进。


肮脏的解决方法:

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));

产地:

#region
static
public class Extensions
{
}
#endregion

哪个编译。

答案 1 :(得分:2)

稍微清理了六个变量提供的hack:将其置于静态方法中,如讨论中所述。

public static void MarkAsStaticClassWithExtensionMethods(this CodeTypeDeclaration class_)
{
   class_.Attributes = MemberAttributes.Public;

   class_.StartDirectives.Add(new CodeRegionDirective(
           CodeRegionMode.Start, Environment.NewLine + "\tstatic"));

   class_.EndDirectives.Add(new CodeRegionDirective(
           CodeRegionMode.End, string.Empty));
}

答案 2 :(得分:1)

您可以获取源代码,将CodeCompileUnit替换为class Extensions并编译该代码,而不是直接编译static class Extensions

答案 3 :(得分:0)

您可以通过将代码直接转换为字符串,然后将其破解来让您的代码准确编译您的需求:

    private static CodeSnippetTypeMember CreateStaticClass(CodeTypeDeclaration type)
    {
        var provider = CodeDomProvider.CreateProvider("CSharp");
        using (var sourceWriter = new StringWriter())
        using (var tabbedWriter = new IndentedTextWriter(sourceWriter, "\t"))
        {
            tabbedWriter.Indent = 2;
            provider.GenerateCodeFromType(type, tabbedWriter, new CodeGeneratorOptions()
            {
                BracingStyle = "C",
                IndentString = "\t"
            });
            return new CodeSnippetTypeMember("\t\t" + sourceWriter.ToString().Replace("public class", "public static class"));
        }
    }