(C#) 在运行时编译 class 并从原始代码调用方法
(C#) Compiling class at runtime and calling methods from original code
我正在尝试在 C# 中在运行时编译代码,然后从编译后的代码中调用函数或初始化在原始代码中定义的 class 。
我目前拥有的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
namespace CTFGame
{
class Program
{
static void Main(string[] args)
{
string code = @"
using System;
namespace CTFGame
{
public class MyPlayer
{
public static void Main ()
{
Console.WriteLine(""Hello world"");
}
/*public void DoTurn ()
{
Program.SayHello();
}*/
}
}
";
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
if (results.Errors.HasErrors)
{
string errors = "";
foreach (CompilerError error in results.Errors)
{
errors += string.Format("Error #{0}: {1}\n", error.ErrorNumber, error.ErrorText);
}
Console.Write(errors);
}
else
{
Assembly assembly = results.CompiledAssembly;
Type program = assembly.GetType("CTFGame.MyPlayer");
MethodInfo main = program.GetMethod("Main");
main.Invoke(null, null);
}
}
public static void SayHello()
{
Console.WriteLine("I'm awesome ><");
}
}
}
现在,运行 运行时加载方法 'Main' 成功,并打印消息 "Hello world"。问题从这里开始:在原始代码中,我有一个名为 "SayHello" 的方法。我想从我的运行时加载代码中调用此方法。
如果我取消注释 "DoTurn" 方法,编译器错误将在运行时显示:
Error #CS0103: The name 'Program' does not exist in the current context
我的问题是 - 这可能吗?如何?
将运行时加载的代码放在同一个命名空间中没有帮助(这是有道理的),那么正确的方法是什么?
谢谢
添加对当前程序集的引用解决了问题:
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
//The next line is the addition to the original code
parameters.ReferencedAssemblies.Add(Assembly.GetEntryAssembly().Location);
我正在尝试在 C# 中在运行时编译代码,然后从编译后的代码中调用函数或初始化在原始代码中定义的 class 。
我目前拥有的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
namespace CTFGame
{
class Program
{
static void Main(string[] args)
{
string code = @"
using System;
namespace CTFGame
{
public class MyPlayer
{
public static void Main ()
{
Console.WriteLine(""Hello world"");
}
/*public void DoTurn ()
{
Program.SayHello();
}*/
}
}
";
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
if (results.Errors.HasErrors)
{
string errors = "";
foreach (CompilerError error in results.Errors)
{
errors += string.Format("Error #{0}: {1}\n", error.ErrorNumber, error.ErrorText);
}
Console.Write(errors);
}
else
{
Assembly assembly = results.CompiledAssembly;
Type program = assembly.GetType("CTFGame.MyPlayer");
MethodInfo main = program.GetMethod("Main");
main.Invoke(null, null);
}
}
public static void SayHello()
{
Console.WriteLine("I'm awesome ><");
}
}
}
现在,运行 运行时加载方法 'Main' 成功,并打印消息 "Hello world"。问题从这里开始:在原始代码中,我有一个名为 "SayHello" 的方法。我想从我的运行时加载代码中调用此方法。
如果我取消注释 "DoTurn" 方法,编译器错误将在运行时显示:
Error #CS0103: The name 'Program' does not exist in the current context
我的问题是 - 这可能吗?如何?
将运行时加载的代码放在同一个命名空间中没有帮助(这是有道理的),那么正确的方法是什么?
谢谢
添加对当前程序集的引用解决了问题:
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateInMemory = true;
//The next line is the addition to the original code
parameters.ReferencedAssemblies.Add(Assembly.GetEntryAssembly().Location);