Compile a C# Array at runtime and use it in code?

2019-02-23 21:49发布

I know C# code can be compiled at runtime using C#. However I'm very very shaky at it since I just read about it a few minutes ago. I learn a lot better by examples. So tell me. If I want to compile something like:

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

and use this array in my code, how would I go about it?

In pseudocode I want to do something like this:

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

3条回答
手持菜刀,她持情操
2楼-- · 2019-02-23 21:57

You can create a class CompiledLevel that inherits from ILevel which proposes a static property Level of type String[].

Then, before compiling, create a fake CompiledLevel.cs file built from a template of class filled with content of LevelMap (wwwggg...) (sort of concatenation).

One compiled, call Level property on the compiled class.

Create a service/factory/whatever to make it fancy :)

查看更多
Luminary・发光体
3楼-- · 2019-02-23 22:00

It appears that you are wanting to compile C# code in order to load a list of strings in a text (C#) file into a string array variable.

You don't need a c# compiler to load a list of strings from a text file into an array in memory. Just put one string per line in your text file, and read the file line by line in your code, adding each line to a List<String>. When you're done, list.ToArray() will produce your array of strings.

查看更多
在下西门庆
4楼-- · 2019-02-23 22:19

LINQ Expression trees are probably the friendliest way of doing this: Perhaps something like:

You can also generate the IL using OpCodes (OpCodes.Newarr). Easy if you are comfortable with stack-based programming (otherwise, can be challenging).

Lastly, you can use the CodeDom (which your pseudocode resembles), but--while the most powerful tool--it is less ideal for quick dynamic methods. It requires file system permissions and manual reference resolution since you are working closely with the compiler.

Sample from MSDN

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

Source - Creating Arrays with the Code DOM

If you want a straight up raw compile of a string, you can omit the object-oriented treatment of the statements and instead just build a big string. Something like:

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() );
查看更多
登录 后发表回答