以编程方式生成 C# 代码文件的干净、高效、可靠的方法

发布于 2024-11-24 18:24:39 字数 564 浏览 3 评论 0原文

我想知道是否有任何好的方法可以以编程方式生成 C# 代码,而无需实际操作字符串或 StringBuilder。此外,它应该检查代码是否编译,但我想这可以使用 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# 动态生成代码),所以如果这看起来毫无头绪,那是因为我就是这样!

I want to know if there is any good way of programmatically producing C# code without actually manipulating strings or StringBuilders. Additionally it should check if the code compiles, but I guess this can be done using CSharpCodeProvider.

I'm looking for something like the following:

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

This might be part of the core library (Don't think CSharpCodeProvider can do this?) or an external library, but this is not my forte at all (dynamically producing code using c#), so if this seems clueless it's because I am!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

帅气尐潴 2024-12-01 18:24:39

这正是 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);

尽管它可能非常冗长。此外,它尝试与语言无关,这意味着您无法使用此 API 来使用特定于 C# 的功能,例如静态类、扩展方法、LINQ 查询表达式或 lambda。不过,您可以做的是将任何字符串放入方法体内。使用此功能,您可以使用一些特定于 C# 的功能,但只能使用您试图避免的字符串操作。

That's exactly what CodeDOM is for:

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

Although it can be quite verbose. Also, it tries to be language-independent, which means you can't use C#-specific features like static classes, extension methods, LINQ query expressions or lambdas using this API. What you can do though, is to put any string inside method body. Using this, you can use some of the C#-specific features, but only using string manipulation, which you were trying to avoid.

野味少女 2024-12-01 18:24:39

您可以使用 Reflection.Emit 类,例如 MethodBuilder。还用它们表达树。它更像是 CLS,而不是 C#。

You can use Reflection.Emit classes like MethodBuilder. Also expression trees with them. It is rather CLS than C#.

乱世争霸 2024-12-01 18:24:39

我已经完成了 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% 运行。 (Compiler 类确实可以工作,该示例可能会错误地使用它)。

源代码:

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

I've done a wrapper around codedom. You only need to create your own C# script and specify the types being used. Namespaces and assemblies will automatically be included.

Example

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

Note that it was a long time ago that I wrote it. The example might not work 100%. (The Compiler class do work, the example might use it incorrectly).

Source code:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文