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?
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
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