2016-08-18 10 views
2

私はCodeDomで少し実験を始め、ユーザー入力からソースコードを収集し、C#-Syntaxでコンパイルしようとする簡単なアプリケーションを作った。CodeDomでコンパイル

すべてのプロセスを試したい人は...と入力してソースコードの入力を完了してください。今

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\");}} 

あなたが(「なしで)そのようにそれを入力するかのように正常に動作しますしかし、1つの行の終了後にEnterキーを押して改行を挿入すると、コンパイル時にいくつかのエラーが発生し、次の文を入力することで各行を独自のプログラムとして評価するようです。

以下の入力の場合
} 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"); 
} 
} 

は、私は、ユーザー(カスタム)を破るする必要がありますかは、1つのラインにダウンエントリ?

答えて

3

ソースの各行には、完全なソースコードが含まれている必要があります。この作品を冷却

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

:あなたがソース配列の中に線でのコード行を収集しているので、あなたは、これを試してみてくださいCompileAssemblyFromSource に渡す配列にその文字列を追加する単一の文字列にそれを崩壊する必要があります実際には何を期待するのかわからないのでコードを崩壊させる必要がありますが、一方ではオブジェクトがCompilerResults、hummという名前になっているので意味があります。ソリューション – prizm1

+0

ファイルから入力を読み取っていた場合、ソース配列の各エントリは、コードの1行ではなく、ソースファイル全体の内容となります – SpaceghostAli

関連する問題