[英]Clean, efficient, infallible method of programmatically generating C# code files
I want to know if there is any good way of programmatically producing C# code without actually manipulating strings or StringBuilders.我想知道是否有任何好的方法可以在不实际操作字符串或 StringBuilders 的情况下以编程方式生成 C# 代码。 Additionally it should check if the code compiles, but I guess this can be done using CSharpCodeProvider.
此外,它应该检查代码是否编译,但我想这可以使用 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!这可能是核心库的一部分(不认为 CSharpCodeProvider 可以做到这一点?)或外部库,但这根本不是我的强项(使用 c# 动态生成代码),所以如果这看起来毫无头绪,那是因为我是!
That's exactly what CodeDOM is for:这正是 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);
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.
此外,它试图独立于语言,这意味着您不能使用 static 类、扩展方法、LINQ 查询表达式或使用此 ZDB974238714CA8DE1434A7CE1DZ08A 的 lambdas 等特定于 C# 的功能。 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.
使用它,您可以使用一些 C# 特定的功能,但只能使用您试图避免的字符串操作。
I like to use the NVelocity Template Engine .我喜欢使用NVelocity 模板引擎。
You can use Reflection.Emit classes like MethodBuilder
.您可以使用
MethodBuilder
类的 Reflection.Emit 类。 Also expression trees with them.还带有它们的表达式树。 It is rather CLS than C#.
它是 CLS 而不是 C#。
I've done a wrapper around codedom.我已经对 codedom 做了一个包装。 You only need to create your own C# script and specify the types being used.
您只需创建自己的 C# 脚本并指定使用的类型。 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%.
该示例可能无法 100% 工作。 (The Compiler class do work, the example might use it incorrectly).
(编译器 class 确实可以工作,示例可能使用不正确)。
Source code:源代码:
http://fadd.codeplex.com/SourceControl/changeset/view/67972#925984 http://fadd.codeplex.com/SourceControl/changeset/view/67972#925984
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.