【问题标题】:Compile a C# Array at runtime and use it in code?在运行时编译一个 C# 数组并在代码中使用它?
【发布时间】:2012-07-29 17:40:30
【问题描述】:

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

【问题讨论】:

  • 你希望通过编译这个字符串数组来实现什么?它会被编译成什么?
  • 我真的不确定你的问题是什么。是关于在运行时创建字符串数组吗?从文本文件中加载字符串怎么样?
  • 在运行时将它读入一个已经编译好的数组可能不会那么复杂和痛苦。
  • 只有一个数组的动态创建的类可能过于复杂......一个动态类的数组已经计算了关于编译到其中的数组的逻辑......这可能是一个很好的使用技术。

标签: c# compiler-construction compilation runtime


【解决方案1】:

LINQ 表达式树可能是最友好的方式:也许是这样的:

您还可以使用操作码 (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() );

【讨论】:

    【解决方案2】:

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

    然后,在编译之前,创建一个伪造的CompiledLevel.cs 文件,该文件是从一个填充了 LevelMap (wwwggg...) 内容的类模板构建的(有点串联)。

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

    创建一个服务/工厂/任何让它看起来很棒的东西:)

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-18
        • 2014-12-04
        • 2021-09-27
        • 1970-01-01
        • 2020-02-19
        相关资源
        最近更新 更多