使用 CodeDom 编译
Compiling with CodeDom
我开始尝试使用 CodeDom 并制作了一个简单的应用程序,该应用程序从用户输入中收集源代码并尝试使用 C# 语法对其进行编译。
对于那些想要尝试整个过程的人,请键入 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");
}
}
然后我必须将用户(自定义)条目分成一行吗?
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 };
我开始尝试使用 CodeDom 并制作了一个简单的应用程序,该应用程序从用户输入中收集源代码并尝试使用 C# 语法对其进行编译。
对于那些想要尝试整个过程的人,请键入 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");
}
}
然后我必须将用户(自定义)条目分成一行吗?
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 };