C# 在编译时使用注释,在运行时从路径中使用 运行 代码

C# Use comment when compiling and running code from path at runtime

最近我尝试编译 运行 C# 代码存储在别处。我的目标是 导入一个 .txt 文件,编译它并 运行 它 。我在 Simeon's blog 上阅读了这篇关于在程序中编译和 运行ning C# 代码的文章,一切正常。

然后我尝试通过从我的计算机导入 C# 代码来制作更复杂的东西,因此我创建了一个包含以下行的 .txt 文件,例如存储在 "C:\program.txt" 中: (文本文件)

using System;
namespace Test
{   
    public class DynaCore   
    {
        static public int Main(string str)       
        {
            Console.WriteLine("Cool it work !");
            return str.Length;       
        }   
    }
}

我根据同一篇文章编写了一些代码,这就是我的代码: (C#程序)

using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom.Compiler;
using System.IO;
using Microsoft.CSharp;
using System.Reflection;

namespace DynaCode
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] lines = System.IO.File.ReadAllLines(@"C:\program.txt");
            string bigLine = string.Empty;
            foreach(string s in lines)
            {
                bigLine += s;
            }
            string[] finalLine = new string[1] { bigLine };
            CompileAndRun(finalLine);

            Console.ReadKey();
        }

        static void CompileAndRun(string[] code)
        {
            CompilerParameters CompilerParams = new CompilerParameters();
            string outputDirectory = Directory.GetCurrentDirectory();

            CompilerParams.GenerateInMemory = true;
            CompilerParams.TreatWarningsAsErrors = false;
            CompilerParams.GenerateExecutable = false;
            CompilerParams.CompilerOptions = "/optimize";

            string[] references = { "System.dll" };
            CompilerParams.ReferencedAssemblies.AddRange(references);

            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerResults compile = provider.CompileAssemblyFromSource(CompilerParams, code);

            if (compile.Errors.HasErrors)
            {
                string text = "Compile error: ";
                foreach (CompilerError ce in compile.Errors)
                {
                    text += "rn" + ce.ToString();
                }
                throw new Exception(text);
            }

            Module module = compile.CompiledAssembly.GetModules()[0];
            Type mt = null;
            MethodInfo methInfo = null;

            if (module != null)
            {
                mt = module.GetType("Test.DynaCore");
            }

            if (mt != null)
            {
                methInfo = mt.GetMethod("Main");
            }

            if (methInfo != null)
            {
                Console.WriteLine(methInfo.Invoke(null, new object[] { "here in dyna code. Yes it work !!" }));
            }
        }
    }
}

这很好用,我得到了预期的以下输出:

Cool it work !
33

请注意,我将 .txt 文件的所有代码放在我自己做的一大行中,因为正如 Simeon 所说:

CompileAssemblyFromSource consumes is a single string for each block (file) worth of C# code, not for each line.

这句话到现在对我来说还是有点晦涩难懂

(我之前试过CompileAndRun(new string[1] { lines.ToString() });但是编译.txt文件时出现错误,所以我自己做了大行。)

这是我的问题:我问自己:"What if I add a comment in my .txt file ?",所以我编辑它,它看起来如何:(文本文件)

using System;

namespace Test
{   
    //This is a super simple test
    public class DynaCore   
    {
        static public int Main(string str)       
        {
            Console.WriteLine("Cool it work !");
            return str.Length;       
        }   
    }
}

当然我得到了一个错误 (CS1513) 因为我将 .txt 文件转换成一个大字符串,所以 [=16= 之后的所有内容] 被忽略。那么,如何在我的 .txt 文件中使用 // 来使用注释并让程序运行?

我也试过CompileAndRun(lines);,但是启动程序后编译.txt文件时因为异常崩溃了。

我做了一些搜索,但没有找到任何关于评论的内容。我想在 CompileAndRun 方法中只传递一大行是有问题的,但是传递几行是行不通的,就像我上面说的那样。 (另一个注意事项:使用 /* insert comment */ 的评论有效。)

提供给 CompileAssemblyFromSource 的每个元素都应该是一个文件,而不是一行代码。因此,将整个文件读入一个字符串并将其提供给该方法,它将正常工作。

static void Main(string[] args)
{
    var code = System.IO.File.ReadAllText(@"C:\program.txt");
    CompileAndRun(code);

    Console.ReadKey();
}

static void CompileAndRun(string code)
{
    CompilerParameters CompilerParams = new CompilerParameters();
    string outputDirectory = Directory.GetCurrentDirectory();

    CompilerParams.GenerateInMemory = true;
    CompilerParams.TreatWarningsAsErrors = false;
    CompilerParams.GenerateExecutable = false;
    CompilerParams.CompilerOptions = "/optimize";

    string[] references = { "System.dll" };
    CompilerParams.ReferencedAssemblies.AddRange(references);

    CSharpCodeProvider provider = new CSharpCodeProvider();
    CompilerResults compile = provider.CompileAssemblyFromSource(CompilerParams, code);
    // ...
}