2011-06-10 99 views
3

我正嘗試使用CodeDOM創建擴展方法。似乎沒有任何支持,並且使用ExtensionAttribute(C#內部用於標記擴展方法)是不允許的。使用CodeDOM創建擴展方法

可以使用a trick指定this修飾符,但是如何製作包含類static,以便代碼實際編譯?

由於static是一個C#概念,它不是通過CodeDOM API公開的。並設置TypeAttributesTypeAttributes.Abstract | TypeAttributes.Sealed | TypeAttributes.Public不起作用,因爲

一個抽象類不能被密封或靜態

如何讓我的擴展方法來編譯?

+1

未來的讀者:我覺得固溶現在是[標籤:Roslyn],併爲這個類添加一個靜態修飾符。 – user7116 2013-04-12 16:20:54

回答

6

我敢肯定你正在尋找:

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

然而,這似乎不工作。有趣的是:

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

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

但是,然而,當你去輸出它,即使Attributes屬性明顯不同於0x000050020x00006003變化沒有變化。

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 

來編譯。

+0

這似乎沒有做任何事情。並且使用'MemberAttributes.Private'不會將類更改爲私有。 – svick 2011-06-10 15:22:26

+0

@svick:奇怪,我已經證實4.0是這種情況。使用舊版本的編譯器進行檢查。 – user7116 2011-06-10 15:41:43

+0

@svick:已更新爲包含使用「CodeRegionDirective」的解決方法。 – user7116 2011-06-10 16:32:53

1

而不是直接編譯CodeCompileUnit,你可以得到源代碼,用static class Extensions代替class Extensions並編譯該代碼。

+0

請注意,我不喜歡這個解決方案,我仍然在尋找更好的解決方案。 – svick 2011-06-10 15:32:58

+0

我已經更新了我的答案,包括爲什麼你必須走這條路線。我已經包含了詳細的MS Connect文章。 – user7116 2011-06-10 16:14:00

2

清除了六個字母變量提供的黑客一點:將其置於靜態方法中,如討論中所述。

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)); 
} 
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")); 
     } 
    } 
+0

是的,這幾乎是我在[我自己的答案](http://stackoverflow.com/a/6308622/41071)中提出的建議。 – svick 2017-04-10 17:25:02

+0

但代碼@svick在哪裏? ;) – Daryl 2017-04-10 17:37:02