2016-08-18 1 views
2

Ich fing an, etwas mit CodeDom zu experimentieren und machte einfache Anwendung, die Quellcode von den Benutzereingaben sammelt und versucht, es mit C# -Syntax zu kompilieren.Kompilieren mit CodeDom

Für diejenigen, die den gesamten Prozess ausprobieren möchten, geben Sie Ende ..., um den Quellcode-Eintrag zu beenden.

Hier ist das Beispiel:

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; 
     } 
    } 
} 

Nun, wie Sie sehen können, im Grunde kompiliert es den folgenden Code:

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

Welche funktioniert gut, wenn man es so (ohne „) eingeben, wie userinput in das Programm, aber sobald Sie einen Zeilenumbruch einfügen, indem Sie die Eingabetaste nach einer Zeile drücken, bricht das Kompilieren mit mehreren Fehlern ab und es scheint so, als ob jede Zeile als eigenes Programm ausgewertet würde:

} 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 

Für folgende Eingabe:

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

Muss ich Benutzer (custom) brechen Einträge dann eine Zeile nach unten?

Antwort

3

Jede Zeile in Quellen sollte vollständigen Quellcode nicht eine einzige Zeile Code enthalten. Da Sie den Code Zeile für Zeile in die Quell-Array sind sammeln, werden Sie es in einem einzigen String zusammenbrechen müssen dann diese Zeichenfolge in ein Array fügen Sie diese CompileAssemblyFromSource passieren Versuchen:

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 }; 
+0

diese Werke kühlen gut :) aber es scheint ziemlich kompliziert für mich, dass sie den Code einklappen müssen, weil Sie nicht wirklich wissen, was zu erwarten ist, aber andererseits sinnvoll ist, da das Objekt CompilerResults heißt, humm .. Ich werde Sie als markieren Lösung – prizm1

+0

Wenn Sie die Eingabe aus Dateien gelesen haben, ist jeder Eintrag im Quellen-Array der Inhalt einer gesamten Quelldatei und nicht einer einzelnen Codezeile – SpaceghostAli