在运行时编译C#数组并在代码中使用它?

时间:2012-07-31 20:55:45

标签: c# compiler-construction compilation runtime

I know C# code can be compiled at runtime using C#。但是,因为我几分钟之前就读过它,所以我非常不稳定。我通过例子学到了很多东西。所以告诉我。如果我想编译类似的东西:

// MapScript.CS
String[] LevelMap = {
"WWWWWWWWWWWWWWWWWWW",
"WGGGGGGGGGGGGGGGGGW",
"WGGGGGGGGGGGGGGGGGW",
"WWWWWWWWWWWWWWWWWWW" };

并在我的代码中使用此数组,我该怎么做呢?

在伪代码中我想做这样的事情:

Open("MapScript.CS");
String[] levelMap = CompileArray("levelMap");
// use the array

3 个答案:

答案 0 :(得分:6)

LINQ表达式树可能是最友好的方式:或许类似于:

您还可以使用OpCodes(OpCodes.Newarr)生成IL。如果您对基于堆栈的编程感到满意,则很容易(否则,可能具有挑战性)。

最后,您可以使用CodeDom(您的伪代码类似),但是 - 虽然是最强大的工具 - 但它不太适合快速动态方法。它需要文件系统权限和手动参考解析,因为您正在与编译器密切合作。

来自MSDN的样本

var ca1 = new CodeArrayCreateExpression("System.Int32", 10);                        
var cv1 = new CodeVariableDeclarationStatement("System.Int32[]", "x", ca1);

Source - Creating Arrays with the Code DOM

如果你想要一个字符串的直接原始编译,你可以省略面向对象的语句处理,而只是构建一个大字符串。类似的东西:

var csc = new CSharpCodeProvider( new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } } );
var cp = new CompilerParameters() {
    GenerateExecutable = false,
    OutputAssembly = outputAssemblyName,
    GenerateInMemory = true
};

cp.ReferencedAssemblies.Add( "mscorlib.dll" );
cp.ReferencedAssemblies.Add( "System.dll" );
cp.ReferencedAssemblies.Add( "System.Core.dll" );

StringBuilder sb = new StringBuilder();

// The string can contain any valid c# code, but remember to resolve your references

sb.Append( "namespace Foo{" );
sb.Append( "using System;" );
sb.Append( "public static class MyClass{");

// your specific scenario
sb.Append( @"public static readonly string[] LevelMap = {
    ""WWWWWWWWWWWWWWWWWWW"",
    ""WGGGGGGGGGGGGGGGGGW"",
    ""WGGGGGGGGGGGGGGGGGW"",
    ""WWWWWWWWWWWWWWWWWWW"" };" );

sb.Append( "}}" );

// "results" will usually contain very detailed error messages
var results = csc.CompileAssemblyFromSource( cp, sb.ToString() );

答案 1 :(得分:2)

您似乎想要编译C#代码,以便将文本(C#)文件中的字符串列表加载到字符串数组变量中。

您不需要c#编译器将文本文件中的字符串列表加载到内存中的数组中。只需在文本文件中每行放一个字符串,然后在代码中逐行读取文件,将每行添加到List<String>。完成后,list.ToArray()将生成您的字符串数组。

答案 2 :(得分:0)

您可以创建一个继承自 ILevel 的类CompiledLevel,该类提出类型为String[]的静态属性 Level

然后,在编译之前,创建一个伪造的CompiledLevel.cs文件,该文件由一个类的模板构建,该模板填充了 LevelMap (wwwggg ...)的内容(连接类型)。

在编译的类上编译一个,调用 Level 属性。

创建一个服务/工厂/无论如何使它变得有趣:)