【问题标题】:Compiling with CodeDom使用 CodeDom 编译
【发布时间】:2016-08-18 12:34:34
【问题描述】:

我开始尝试使用 CodeDom 并制作了一个简单的应用程序,它从用户输入中收集源代码并尝试使用 C#-Syntax 编译它。

如果您想尝试整个过程,请键入 end... 以完成源代码条目。

示例如下:

using System;
using System.Collections;
using System.Reflection;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.CSharp;
using System.CodeDom.Compiler;

namespace CodeDomTest
{
    class Program
    {
        static void Main(string[] args)
        {
            getTestCode();
        }

        public static Assembly getTestCode()
        {
            CompilerParameters CompilerOptions = new CompilerParameters(
                assemblyNames: new String[] { "mscorlib.dll", "System.dll", "System.Core.dll" }, 
                outputName: "test.dll", 
                includeDebugInformation: false) 
            { TreatWarningsAsErrors = true, WarningLevel = 0, GenerateExecutable = false, GenerateInMemory = true };
            List<String> newList = new List<String>();
            String a = null;
            while(a != "end...")
            {
                a = Console.ReadLine();
                if (!a.Equals( "end..."))
                    newList.Add(a);
            }
            String[] source = { "class Test {static void test() {System.Console.WriteLine(\"test\");}}" };
            source = newList.ToArray();
            CSharpCodeProvider zb = new CSharpCodeProvider(new Dictionary<String, String> { { "CompilerVersion", "v4.0" } });
            CompilerResults Results = zb.CompileAssemblyFromSource(CompilerOptions, source);
            Console.WriteLine(Results.Errors.HasErrors);
            CompilerErrorCollection errs = Results.Errors;
            foreach(CompilerError z in errs) 
            {
                Console.WriteLine(z.ErrorText);
            }
            if (!(errs.Count > 0)) 
            {
                AssemblyName assemblyRef = Results.CompiledAssembly.GetName();
                AppDomain.CurrentDomain.Load(assemblyRef);
                //foreach (String a in )
                Console.WriteLine(Results.CompiledAssembly.FullName.ToString());
                Type tempType = Results.CompiledAssembly.GetType("Test");
                MethodInfo tempMethodInfo = tempType.GetMethod("test", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
                if (tempMethodInfo != null)
                    tempMethodInfo.Invoke(null,null);
            }
            Console.ReadLine();
            return null;
        }
    }
}

现在你可以看到,基本上它编译了以下代码:

class Test {static void test() {System.Console.WriteLine(\"test\");}}

如果你这样输入它(没有“)作为用户输入到程序中,效果很好。但是一旦你在一个完成的行后按回车键插入换行符,编译就会中断几个错误。看起来像它会通过给出以下语句将每一行评估为自己的程序:

} expected
Expected class, delegate, enum, interface, or struct
A namespace cannot directly contain members such as fields or methods
A namespace cannot directly contain members such as fields or methods
Type or namespace definition, or end-of-file expected
Type or namespace definition, or end-of-file expected

对于以下输入:

class Test 
{
static void test() 
{
System.Console.WriteLine
("test");
}
}

我是否必须将用户(自定义)条目分解为一行?

【问题讨论】:

    标签: c# compilation codedom


    【解决方案1】:

    sources 中的每一行都应该包含完整的源代码,而不是一行代码。由于您将代码逐行收集到源数组中,因此您必须将其折叠成单个字符串,然后将该字符串添加到数组中以传递给 CompileAssemblyFromSource 试试这个:

     while (a != "end...")
     {
         a = Console.ReadLine();
         if (!a.Equals("end..."))
             newList.Add(a);
     }
    
     string code = string.Join("\r\n", newList);
     string[] source = new string[] { code };
    

    【讨论】:

    • cool 这很好用 :) 但对我来说他们需要折叠代码似乎相当复杂,因为你真的不知道会发生什么,但另一方面是有意义的,因为对象是命名为 CompilerResults,嗯.. 我会把你标记为解决方案
    • 如果您从文件中读取输入,则源数组中的每个条目都是整个源文件的内容,而不是单行代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多