簡體   English   中英

以編程方式生成 C# 代碼文件的干凈、高效、可靠的方法

[英]Clean, efficient, infallible method of programmatically generating C# code files

我想知道是否有任何好的方法可以在不實際操作字符串或 StringBuilders 的情況下以編程方式生成 C# 代碼。 此外,它應該檢查代碼是否編譯,但我想這可以使用 CSharpCodeProvider 來完成。

我正在尋找類似以下的內容:

CodeUnit unit = new CodeUnit();
unit.AddDefaultUsings();
unit.AddUsing("MyApi.CoolNameSpace", "MyApi.Yay");
var clazz = unit.AddClass("GeneratedClass", Access.Public);
clazz.AddConstructor("....");
if(unit.Compile() != true)
    //oh dang, somethings wrong!
else unit.WriteUTF8To("GeneratedClass.cs");

這可能是核心庫的一部分(不認為 CSharpCodeProvider 可以做到這一點?)或外部庫,但這根本不是我的強項(使用 c# 動態生成代碼),所以如果這看起來毫無頭緒,那是因為我是!

這正是 CodeDOM 的用途:

var unit = new CodeCompileUnit();

var @namespace = new CodeNamespace("GeneratedCode");
unit.Namespaces.Add(@namespace);

// AddDefault() doesn't exist, but you can create it as an extension method
@namespace.Imports.AddDefault();
@namespace.Imports.Add(new CodeNamespaceImport("MyApi.CoolNameSpace"));

var @class = new CodeTypeDeclaration("GeneratedClass");
@namespace.Types.Add(@class);

@class.TypeAttributes = TypeAttributes.Class | TypeAttributes.Public;

var constructor = new CodeConstructor();
constructor.Attributes = MemberAttributes.Public;
constructor.Parameters.Add(
    new CodeParameterDeclarationExpression(typeof(string), "name"));

constructor.Statements.Add(…);

@class.Members.Add(constructor);

var provider = new CSharpCodeProvider();

var result = provider.CompileAssemblyFromDom(new CompilerParameters(), unit);

雖然它可能非常冗長。 此外,它試圖獨立於語言,這意味着您不能使用 static 類、擴展方法、LINQ 查詢表達式或使用此 ZDB974238714CA8DE1434A7CE1DZ08A 的 lambdas 等特定於 C# 的功能。 但是,您可以做的是將任何字符串放入方法主體中。 使用它,您可以使用一些 C# 特定的功能,但只能使用您試圖避免的字符串操作。

我喜歡使用NVelocity 模板引擎

您可以使用MethodBuilder類的 Reflection.Emit 類。 還帶有它們的表達式樹。 它是 CLS 而不是 C#。

我已經對 codedom 做了一個包裝。 您只需創建自己的 C# 腳本並指定使用的類型。 命名空間和程序集將自動包含在內。

例子

public interface IWorld
{
    string Hello(string value);
}

string code = @"namespace MyNamespace
{
  class Temp : IWorld
  {
      public string Hello(string value)
      {
          return ""World "" + value;
      }
  }
}";

Compiler compiler = new Compiler();
compiler.AddType(typeof(string));
compiler.Compile(code);
var obj = compiler.CreateInstance<IWorld>();
string result = obj.Hello("World!");

請注意,我寫它是很久以前的事了。 該示例可能無法 100% 工作。 (編譯器 class 確實可以工作,示例可能使用不正確)。

源代碼:

http://fadd.codeplex.com/SourceControl/changeset/view/67972#925984

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM