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

微笑、不失礼 提交于 2020-01-21 11:57:06

问题


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

回答1:


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

  • http://msdn.microsoft.com/en-us/library/system.linq.expressions.newarrayexpression.aspx
  • http://msdn.microsoft.com/en-us/library/bb357903.aspx

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



回答2:


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.




回答3:


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



来源:https://stackoverflow.com/questions/11748867/compile-a-c-sharp-array-at-runtime-and-use-it-in-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!